Completed
Branch TASK/update-about-page (5cee29)
by
unknown
34:34 queued 26:08
created

Transactions_Admin_Page::recalculateLineItems()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 0
dl 0
loc 24
rs 9.536
c 0
b 0
f 0
1
<?php
2
3
use EventEspresso\core\exceptions\InvalidDataTypeException;
4
use EventEspresso\core\exceptions\InvalidInterfaceException;
5
6
/**
7
 * EE_Admin_Transactions class
8
 *
9
 * @package     Event Espresso
10
 * @subpackage  includes/core/admin/transactions/Transactions_Admin_Page.core.php
11
 * @author      Brent Christensen
12
 */
13
class Transactions_Admin_Page extends EE_Admin_Page
14
{
15
16
    /**
17
     * @var EE_Transaction
18
     */
19
    private $_transaction;
20
21
    /**
22
     * @var EE_Session
23
     */
24
    private $_session;
25
26
    /**
27
     * @var array $_txn_status
28
     */
29
    private static $_txn_status;
30
31
    /**
32
     * @var array $_pay_status
33
     */
34
    private static $_pay_status;
35
36
    /**
37
     * @var array $_existing_reg_payment_REG_IDs
38
     */
39
    protected $_existing_reg_payment_REG_IDs;
40
41
42
    /**
43
     *    _init_page_props
44
     *
45
     * @return void
46
     */
47 View Code Duplication
    protected function _init_page_props()
48
    {
49
        $this->page_slug = TXN_PG_SLUG;
50
        $this->page_label = esc_html__('Transactions', 'event_espresso');
51
        $this->_admin_base_url = TXN_ADMIN_URL;
52
        $this->_admin_base_path = TXN_ADMIN;
53
    }
54
55
56
    /**
57
     *    _ajax_hooks
58
     *
59
     * @return void
60
     */
61
    protected function _ajax_hooks()
62
    {
63
        add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
64
        add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
65
        add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
66
    }
67
68
69
    /**
70
     *    _define_page_props
71
     *
72
     * @return void
73
     */
74 View Code Duplication
    protected function _define_page_props()
75
    {
76
        $this->_admin_page_title = $this->page_label;
77
        $this->_labels = array(
78
            'buttons' => array(
79
                'add'    => esc_html__('Add New Transaction', 'event_espresso'),
80
                'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
81
                'delete' => esc_html__('Delete Transaction', 'event_espresso'),
82
            ),
83
        );
84
    }
85
86
87
    /**
88
     *        grab url requests and route them
89
     *
90
     * @access private
91
     * @return void
92
     * @throws EE_Error
93
     * @throws InvalidArgumentException
94
     * @throws InvalidDataTypeException
95
     * @throws InvalidInterfaceException
96
     */
97
    public function _set_page_routes()
98
    {
99
100
        $this->_set_transaction_status_array();
101
102
        $txn_id = ! empty($this->_req_data['TXN_ID'])
103
                  && ! is_array($this->_req_data['TXN_ID'])
104
            ? $this->_req_data['TXN_ID']
105
            : 0;
106
107
        $this->_page_routes = array(
108
109
            'default' => array(
110
                'func'       => '_transactions_overview_list_table',
111
                'capability' => 'ee_read_transactions',
112
            ),
113
114
            'view_transaction' => array(
115
                'func'       => '_transaction_details',
116
                'capability' => 'ee_read_transaction',
117
                'obj_id'     => $txn_id,
118
            ),
119
120
            'send_payment_reminder' => array(
121
                'func'       => '_send_payment_reminder',
122
                'noheader'   => true,
123
                'capability' => 'ee_send_message',
124
            ),
125
126
            'espresso_apply_payment' => array(
127
                'func'       => 'apply_payments_or_refunds',
128
                'noheader'   => true,
129
                'capability' => 'ee_edit_payments',
130
            ),
131
132
            'espresso_apply_refund' => array(
133
                'func'       => 'apply_payments_or_refunds',
134
                'noheader'   => true,
135
                'capability' => 'ee_edit_payments',
136
            ),
137
138
            'espresso_delete_payment' => array(
139
                'func'       => 'delete_payment',
140
                'noheader'   => true,
141
                'capability' => 'ee_delete_payments',
142
            ),
143
144
            'espresso_recalculate_line_items' => array(
145
                'func'       => 'recalculateLineItems',
146
                'noheader'   => true,
147
                'capability' => 'ee_edit_payments',
148
            ),
149
150
        );
151
    }
152
153
154
    protected function _set_page_config()
155
    {
156
        $this->_page_config = array(
157
            'default'          => array(
158
                'nav'           => array(
159
                    'label' => esc_html__('Overview', 'event_espresso'),
160
                    'order' => 10,
161
                ),
162
                'list_table'    => 'EE_Admin_Transactions_List_Table',
163
                'help_tabs'     => array(
164
                    'transactions_overview_help_tab'                       => array(
165
                        'title'    => esc_html__('Transactions Overview', 'event_espresso'),
166
                        'filename' => 'transactions_overview',
167
                    ),
168
                    'transactions_overview_table_column_headings_help_tab' => array(
169
                        'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
170
                        'filename' => 'transactions_overview_table_column_headings',
171
                    ),
172
                    'transactions_overview_views_filters_help_tab'         => array(
173
                        'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
174
                        'filename' => 'transactions_overview_views_filters_search',
175
                    ),
176
                ),
177
                'help_tour'     => array('Transactions_Overview_Help_Tour'),
178
                /**
179
                 * commented out because currently we are not displaying tips for transaction list table status but this
180
                 * may change in a later iteration so want to keep the code for then.
181
                 */
182
                // 'qtips' => array( 'Transactions_List_Table_Tips' ),
183
                'require_nonce' => false,
184
            ),
185
            'view_transaction' => array(
186
                'nav'       => array(
187
                    'label'      => esc_html__('View Transaction', 'event_espresso'),
188
                    'order'      => 5,
189
                    'url'        => isset($this->_req_data['TXN_ID'])
190
                        ? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url)
191
                        : $this->_admin_base_url,
192
                    'persistent' => false,
193
                ),
194
                'help_tabs' => array(
195
                    'transactions_view_transaction_help_tab'                                              => array(
196
                        'title'    => esc_html__('View Transaction', 'event_espresso'),
197
                        'filename' => 'transactions_view_transaction',
198
                    ),
199
                    'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
200
                        'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
201
                        'filename' => 'transactions_view_transaction_transaction_details_table',
202
                    ),
203
                    'transactions_view_transaction_attendees_registered_help_tab'                         => array(
204
                        'title'    => esc_html__('Attendees Registered', 'event_espresso'),
205
                        'filename' => 'transactions_view_transaction_attendees_registered',
206
                    ),
207
                    'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
208
                        'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
209
                        'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
210
                    ),
211
                ),
212
                'qtips'     => array('Transaction_Details_Tips'),
213
                'help_tour' => array('Transaction_Details_Help_Tour'),
214
                'metaboxes' => array('_transaction_details_metaboxes'),
215
216
                'require_nonce' => false,
217
            ),
218
        );
219
    }
220
221
222
    /**
223
     * The below methods aren't used by this class currently
224
     */
225
    protected function _add_screen_options()
226
    {
227
        // noop
228
    }
229
230
231
    protected function _add_feature_pointers()
232
    {
233
        // noop
234
    }
235
236
237
    public function admin_init()
238
    {
239
        // IF a registration was JUST added via the admin...
240
        if (isset(
241
            $this->_req_data['redirect_from'],
242
            $this->_req_data['EVT_ID'],
243
            $this->_req_data['event_name']
244
        )) {
245
            // then set a cookie so that we can block any attempts to use
246
            // the back button as a way to enter another registration.
247
            setcookie(
248
                'ee_registration_added',
249
                $this->_req_data['EVT_ID'],
250
                time() + WEEK_IN_SECONDS,
251
                '/'
252
            );
253
            // and update the global
254
            $_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
255
        }
256
        EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
257
            '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.',
258
            'event_espresso'
259
        );
260
        EE_Registry::$i18n_js_strings['error_occurred'] = esc_html__(
261
            'An error occurred! Please refresh the page and try again.',
262
            'event_espresso'
263
        );
264
        EE_Registry::$i18n_js_strings['txn_status_array'] = self::$_txn_status;
265
        EE_Registry::$i18n_js_strings['pay_status_array'] = self::$_pay_status;
266
        EE_Registry::$i18n_js_strings['payments_total'] = esc_html__('Payments Total', 'event_espresso');
267
        EE_Registry::$i18n_js_strings['transaction_overpaid'] = esc_html__(
268
            'This transaction has been overpaid ! Payments Total',
269
            'event_espresso'
270
        );
271
    }
272
273
274
    public function admin_notices()
275
    {
276
        // noop
277
    }
278
279
280
    public function admin_footer_scripts()
281
    {
282
        // noop
283
    }
284
285
286
    /**
287
     * _set_transaction_status_array
288
     * sets list of transaction statuses
289
     *
290
     * @access private
291
     * @return void
292
     * @throws EE_Error
293
     * @throws InvalidArgumentException
294
     * @throws InvalidDataTypeException
295
     * @throws InvalidInterfaceException
296
     */
297
    private function _set_transaction_status_array()
298
    {
299
        self::$_txn_status = EEM_Transaction::instance()->status_array(true);
300
    }
301
302
303
    /**
304
     * get_transaction_status_array
305
     * return the transaction status array for wp_list_table
306
     *
307
     * @access public
308
     * @return array
309
     */
310
    public function get_transaction_status_array()
311
    {
312
        return self::$_txn_status;
313
    }
314
315
316
    /**
317
     *    get list of payment statuses
318
     *
319
     * @access private
320
     * @return void
321
     * @throws EE_Error
322
     * @throws InvalidArgumentException
323
     * @throws InvalidDataTypeException
324
     * @throws InvalidInterfaceException
325
     */
326
    private function _get_payment_status_array()
327
    {
328
        self::$_pay_status = EEM_Payment::instance()->status_array(true);
329
        $this->_template_args['payment_status'] = self::$_pay_status;
330
    }
331
332
333
    /**
334
     *    _add_screen_options_default
335
     *
336
     * @access protected
337
     * @return void
338
     * @throws InvalidArgumentException
339
     * @throws InvalidDataTypeException
340
     * @throws InvalidInterfaceException
341
     */
342
    protected function _add_screen_options_default()
343
    {
344
        $this->_per_page_screen_option();
345
    }
346
347
348
    /**
349
     * load_scripts_styles
350
     *
351
     * @access public
352
     * @return void
353
     */
354
    public function load_scripts_styles()
355
    {
356
        // enqueue style
357
        wp_register_style(
358
            'espresso_txn',
359
            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
360
            array(),
361
            EVENT_ESPRESSO_VERSION
362
        );
363
        wp_enqueue_style('espresso_txn');
364
        // scripts
365
        wp_register_script(
366
            'espresso_txn',
367
            TXN_ASSETS_URL . 'espresso_transactions_admin.js',
368
            array(
369
                'ee_admin_js',
370
                'ee-datepicker',
371
                'jquery-ui-datepicker',
372
                'jquery-ui-draggable',
373
                'ee-dialog',
374
                'ee-accounting',
375
                'ee-serialize-full-array',
376
            ),
377
            EVENT_ESPRESSO_VERSION,
378
            true
379
        );
380
        wp_enqueue_script('espresso_txn');
381
    }
382
383
384
    /**
385
     *    load_scripts_styles_view_transaction
386
     *
387
     * @access public
388
     * @return void
389
     */
390
    public function load_scripts_styles_view_transaction()
391
    {
392
        // styles
393
        wp_enqueue_style('espresso-ui-theme');
394
    }
395
396
397
    /**
398
     *    load_scripts_styles_default
399
     *
400
     * @access public
401
     * @return void
402
     */
403
    public function load_scripts_styles_default()
404
    {
405
        // styles
406
        wp_enqueue_style('espresso-ui-theme');
407
    }
408
409
410
    /**
411
     *    _set_list_table_views_default
412
     *
413
     * @access protected
414
     * @return void
415
     */
416
    protected function _set_list_table_views_default()
417
    {
418
        $this->_views = array(
419
            'all'        => array(
420
                'slug'  => 'all',
421
                'label' => esc_html__('View All Transactions', 'event_espresso'),
422
                'count' => 0,
423
            ),
424
            'abandoned'  => array(
425
                'slug'  => 'abandoned',
426
                'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
427
                'count' => 0,
428
            ),
429
            'incomplete' => array(
430
                'slug'  => 'incomplete',
431
                'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
432
                'count' => 0,
433
            ),
434
        );
435
        if (/**
436
         * Filters whether a link to the "Failed Transactions" list table
437
         * appears on the Transactions Admin Page list table.
438
         * List display can be turned back on via the following:
439
         * add_filter(
440
         *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
441
         *     '__return_true'
442
         * );
443
         *
444
         * @since 4.9.70.p
445
         * @param boolean                 $display_failed_txns_list
446
         * @param Transactions_Admin_Page $this
447
         */
448
        apply_filters(
449
            'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
450
            false,
451
            $this
452
        )
453
        ) {
454
            $this->_views['failed'] = array(
455
                'slug'  => 'failed',
456
                'label' => esc_html__('Failed Transactions', 'event_espresso'),
457
                'count' => 0,
458
            );
459
        }
460
    }
461
462
463
    /**
464
     * _set_transaction_object
465
     * This sets the _transaction property for the transaction details screen
466
     *
467
     * @access private
468
     * @return void
469
     * @throws EE_Error
470
     * @throws InvalidArgumentException
471
     * @throws RuntimeException
472
     * @throws InvalidDataTypeException
473
     * @throws InvalidInterfaceException
474
     * @throws ReflectionException
475
     */
476
    private function _set_transaction_object()
477
    {
478
        if ($this->_transaction instanceof EE_Transaction) {
479
            return;
480
        } //get out we've already set the object
481
482
        $TXN_ID = ! empty($this->_req_data['TXN_ID'])
483
            ? absint($this->_req_data['TXN_ID'])
484
            : false;
485
486
        // get transaction object
487
        $this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
488
        $this->_session = $this->_transaction instanceof EE_Transaction
489
            ? $this->_transaction->session_data()
490
            : null;
491
        if ($this->_transaction instanceof EE_Transaction) {
492
            $this->_transaction->verify_abandoned_transaction_status();
493
        }
494
495
        if (! $this->_transaction instanceof EE_Transaction) {
496
            $error_msg = sprintf(
497
                esc_html__(
498
                    'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
499
                    'event_espresso'
500
                ),
501
                $TXN_ID
502
            );
503
            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
504
        }
505
    }
506
507
508
    /**
509
     *    _transaction_legend_items
510
     *
511
     * @access protected
512
     * @return array
513
     * @throws EE_Error
514
     * @throws InvalidArgumentException
515
     * @throws ReflectionException
516
     * @throws InvalidDataTypeException
517
     * @throws InvalidInterfaceException
518
     */
519
    protected function _transaction_legend_items()
520
    {
521
        EE_Registry::instance()->load_helper('MSG_Template');
522
        $items = array();
523
524 View Code Duplication
        if (EE_Registry::instance()->CAP->current_user_can(
525
            'ee_read_global_messages',
526
            'view_filtered_messages'
527
        )) {
528
            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
529
            if (is_array($related_for_icon)
530
                && isset($related_for_icon['css_class'], $related_for_icon['label'])
531
            ) {
532
                $items['view_related_messages'] = array(
533
                    'class' => $related_for_icon['css_class'],
534
                    'desc'  => $related_for_icon['label'],
535
                );
536
            }
537
        }
538
539
        $items = apply_filters(
540
            'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
541
            array_merge(
542
                $items,
543
                array(
544
                    'view_details'          => array(
545
                        'class' => 'dashicons dashicons-cart',
546
                        'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
547
                    ),
548
                    'view_invoice'          => array(
549
                        'class' => 'dashicons dashicons-media-spreadsheet',
550
                        'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
551
                    ),
552
                    'view_receipt'          => array(
553
                        'class' => 'dashicons dashicons-media-default',
554
                        'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
555
                    ),
556
                    'view_registration'     => array(
557
                        'class' => 'dashicons dashicons-clipboard',
558
                        'desc'  => esc_html__('View Registration Details', 'event_espresso'),
559
                    ),
560
                    'payment_overview_link' => array(
561
                        'class' => 'dashicons dashicons-money',
562
                        'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
563
                    ),
564
                )
565
            )
566
        );
567
568 View Code Duplication
        if (EEH_MSG_Template::is_mt_active('payment_reminder')
569
            && EE_Registry::instance()->CAP->current_user_can(
570
                'ee_send_message',
571
                'espresso_transactions_send_payment_reminder'
572
            )
573
        ) {
574
            $items['send_payment_reminder'] = array(
575
                'class' => 'dashicons dashicons-email-alt',
576
                'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
577
            );
578
        } else {
579
            $items['blank*'] = array(
580
                'class' => '',
581
                'desc'  => '',
582
            );
583
        }
584
        $more_items = apply_filters(
585
            'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
586
            array(
587
                'overpaid'   => array(
588
                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
589
                    'desc'  => EEH_Template::pretty_status(
590
                        EEM_Transaction::overpaid_status_code,
591
                        false,
592
                        'sentence'
593
                    ),
594
                ),
595
                'complete'   => array(
596
                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
597
                    'desc'  => EEH_Template::pretty_status(
598
                        EEM_Transaction::complete_status_code,
599
                        false,
600
                        'sentence'
601
                    ),
602
                ),
603
                'incomplete' => array(
604
                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
605
                    'desc'  => EEH_Template::pretty_status(
606
                        EEM_Transaction::incomplete_status_code,
607
                        false,
608
                        'sentence'
609
                    ),
610
                ),
611
                'abandoned'  => array(
612
                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
613
                    'desc'  => EEH_Template::pretty_status(
614
                        EEM_Transaction::abandoned_status_code,
615
                        false,
616
                        'sentence'
617
                    ),
618
                ),
619
                'failed'     => array(
620
                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
621
                    'desc'  => EEH_Template::pretty_status(
622
                        EEM_Transaction::failed_status_code,
623
                        false,
624
                        'sentence'
625
                    ),
626
                ),
627
            )
628
        );
629
630
        return array_merge($items, $more_items);
631
    }
632
633
634
    /**
635
     *    _transactions_overview_list_table
636
     *
637
     * @access protected
638
     * @return void
639
     * @throws DomainException
640
     * @throws EE_Error
641
     * @throws InvalidArgumentException
642
     * @throws InvalidDataTypeException
643
     * @throws InvalidInterfaceException
644
     * @throws ReflectionException
645
     */
646
    protected function _transactions_overview_list_table()
647
    {
648
        $this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
649
        $event = isset($this->_req_data['EVT_ID'])
650
            ? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID'])
651
            : null;
652
        $this->_template_args['admin_page_header'] = $event instanceof EE_Event
653
            ? sprintf(
654
                esc_html__(
655
                    '%sViewing Transactions for the Event: %s%s',
656
                    'event_espresso'
657
                ),
658
                '<h3>',
659
                '<a href="'
660
                . EE_Admin_Page::add_query_args_and_nonce(
661
                    array('action' => 'edit', 'post' => $event->ID()),
662
                    EVENTS_ADMIN_URL
663
                )
664
                . '" title="'
665
                . esc_attr__(
666
                    'Click to Edit event',
667
                    'event_espresso'
668
                )
669
                . '">' . $event->name() . '</a>',
670
                '</h3>'
671
            )
672
            : '';
673
        $this->_template_args['after_list_table'] = $this->_display_legend($this->_transaction_legend_items());
674
        $this->display_admin_list_table_page_with_no_sidebar();
675
    }
676
677
678
    /**
679
     *    _transaction_details
680
     * generates HTML for the View Transaction Details Admin page
681
     *
682
     * @access protected
683
     * @return void
684
     * @throws DomainException
685
     * @throws EE_Error
686
     * @throws InvalidArgumentException
687
     * @throws InvalidDataTypeException
688
     * @throws InvalidInterfaceException
689
     * @throws RuntimeException
690
     * @throws ReflectionException
691
     */
692
    protected function _transaction_details()
693
    {
694
        do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
695
696
        $this->_set_transaction_status_array();
697
698
        $this->_template_args = array();
699
        $this->_template_args['transactions_page'] = $this->_wp_page_slug;
700
701
        $this->_set_transaction_object();
702
703
        if (! $this->_transaction instanceof EE_Transaction) {
704
            return;
705
        }
706
        $primary_registration = $this->_transaction->primary_registration();
707
        $attendee = $primary_registration instanceof EE_Registration
0 ignored issues
show
Unused Code introduced by
$attendee is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
708
            ? $primary_registration->attendee()
709
            : null;
710
711
        $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
712
        $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
713
714
        $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
715
        $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
716
717
        $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
718
        $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
719
        $this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->status_ID();
720
721
        $this->_template_args['grand_total'] = $this->_transaction->total();
722
        $this->_template_args['total_paid'] = $this->_transaction->paid();
723
724
        $amount_due = $this->_transaction->total() - $this->_transaction->paid();
725
        $this->_template_args['amount_due'] = EEH_Template::format_currency(
726
            $amount_due,
727
            true
728
        );
729
        if (EE_Registry::instance()->CFG->currency->sign_b4) {
730
            $this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign
731
                                                  . $this->_template_args['amount_due'];
732
        } else {
733
            $this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign;
734
        }
735
        $this->_template_args['amount_due_class'] = '';
736
737
        if ($this->_transaction->paid() === $this->_transaction->total()) {
738
            // paid in full
739
            $this->_template_args['amount_due'] = false;
740
        } elseif ($this->_transaction->paid() > $this->_transaction->total()) {
741
            // overpaid
742
            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
743
        } elseif ($this->_transaction->total() > (float) 0) {
744
            if ($this->_transaction->paid() > (float) 0) {
745
                // monies owing
746
                $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
747
            } elseif ($this->_transaction->paid() === (float) 0) {
748
                // no payments made yet
749
                $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
750
            }
751
        } elseif ($this->_transaction->total() === (float) 0) {
752
            // free event
753
            $this->_template_args['amount_due'] = false;
754
        }
755
756
        $payment_method = $this->_transaction->payment_method();
757
758
        $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
759
            ? $payment_method->admin_name()
760
            : esc_html__('Unknown', 'event_espresso');
761
762
        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
763
        // link back to overview
764
        $this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER'])
765
            ? $_SERVER['HTTP_REFERER']
766
            : TXN_ADMIN_URL;
767
768
769
        // next link
770
        $next_txn = $this->_transaction->next(
771
            null,
772
            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
773
            'TXN_ID'
774
        );
775
        $this->_template_args['next_transaction'] = $next_txn
776
            ? $this->_next_link(
777
                EE_Admin_Page::add_query_args_and_nonce(
778
                    array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
779
                    TXN_ADMIN_URL
780
                ),
781
                'dashicons dashicons-arrow-right ee-icon-size-22'
782
            )
783
            : '';
784
        // previous link
785
        $previous_txn = $this->_transaction->previous(
786
            null,
787
            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
788
            'TXN_ID'
789
        );
790
        $this->_template_args['previous_transaction'] = $previous_txn
791
            ? $this->_previous_link(
792
                EE_Admin_Page::add_query_args_and_nonce(
793
                    array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
794
                    TXN_ADMIN_URL
795
                ),
796
                'dashicons dashicons-arrow-left ee-icon-size-22'
797
            )
798
            : '';
799
800
        // were we just redirected here after adding a new registration ???
801
        if (isset(
802
            $this->_req_data['redirect_from'],
803
            $this->_req_data['EVT_ID'],
804
            $this->_req_data['event_name']
805
        )) {
806
            if (EE_Registry::instance()->CAP->current_user_can(
807
                'ee_edit_registrations',
808
                'espresso_registrations_new_registration',
809
                $this->_req_data['EVT_ID']
810
            )) {
811
                $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
812
                $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
813
                    array(
814
                        'page'     => 'espresso_registrations',
815
                        'action'   => 'new_registration',
816
                        'return'   => 'default',
817
                        'TXN_ID'   => $this->_transaction->ID(),
818
                        'event_id' => $this->_req_data['EVT_ID'],
819
                    ),
820
                    REG_ADMIN_URL
821
                );
822
                $this->_admin_page_title .= '">';
823
824
                $this->_admin_page_title .= sprintf(
825
                    esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
826
                    htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
827
                );
828
                $this->_admin_page_title .= '</a>';
829
            }
830
            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
831
        }
832
        // grab messages at the last second
833
        $this->_template_args['notices'] = EE_Error::get_notices();
834
        // path to template
835
        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
836
        $this->_template_args['admin_page_header'] = EEH_Template::display_template(
837
            $template_path,
838
            $this->_template_args,
839
            true
840
        );
841
842
        // the details template wrapper
843
        $this->display_admin_page_with_sidebar();
844
    }
845
846
847
    /**
848
     *        _transaction_details_metaboxes
849
     *
850
     * @access protected
851
     * @return void
852
     * @throws EE_Error
853
     * @throws InvalidArgumentException
854
     * @throws InvalidDataTypeException
855
     * @throws InvalidInterfaceException
856
     * @throws RuntimeException
857
     * @throws ReflectionException
858
     */
859
    protected function _transaction_details_metaboxes()
860
    {
861
862
        $this->_set_transaction_object();
863
864
        if (! $this->_transaction instanceof EE_Transaction) {
865
            return;
866
        }
867
        add_meta_box(
868
            'edit-txn-details-mbox',
869
            esc_html__('Transaction Details', 'event_espresso'),
870
            array($this, 'txn_details_meta_box'),
871
            $this->_wp_page_slug,
872
            'normal',
873
            'high'
874
        );
875
        add_meta_box(
876
            'edit-txn-attendees-mbox',
877
            esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
878
            array($this, 'txn_attendees_meta_box'),
879
            $this->_wp_page_slug,
880
            'normal',
881
            'high',
882
            array('TXN_ID' => $this->_transaction->ID())
883
        );
884
        add_meta_box(
885
            'edit-txn-registrant-mbox',
886
            esc_html__('Primary Contact', 'event_espresso'),
887
            array($this, 'txn_registrant_side_meta_box'),
888
            $this->_wp_page_slug,
889
            'side',
890
            'high'
891
        );
892
        add_meta_box(
893
            'edit-txn-billing-info-mbox',
894
            esc_html__('Billing Information', 'event_espresso'),
895
            array($this, 'txn_billing_info_side_meta_box'),
896
            $this->_wp_page_slug,
897
            'side',
898
            'high'
899
        );
900
    }
901
902
903
    /**
904
     * Callback for transaction actions metabox.
905
     *
906
     * @param EE_Transaction|null $transaction
907
     * @return string
908
     * @throws DomainException
909
     * @throws EE_Error
910
     * @throws InvalidArgumentException
911
     * @throws InvalidDataTypeException
912
     * @throws InvalidInterfaceException
913
     * @throws ReflectionException
914
     * @throws RuntimeException
915
     */
916
    public function getActionButtons(EE_Transaction $transaction = null)
917
    {
918
        $content = '';
919
        $actions = array();
920
        if (! $transaction instanceof EE_Transaction) {
921
            return $content;
922
        }
923
        /** @var EE_Registration $primary_registration */
924
        $primary_registration = $transaction->primary_registration();
925
        $attendee = $primary_registration instanceof EE_Registration
926
            ? $primary_registration->attendee()
927
            : null;
928
929
        if ($attendee instanceof EE_Attendee
930
            && EE_Registry::instance()->CAP->current_user_can(
931
                'ee_send_message',
932
                'espresso_transactions_send_payment_reminder'
933
            )
934
        ) {
935
            $actions['payment_reminder'] =
936
                EEH_MSG_Template::is_mt_active('payment_reminder')
937
                && $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
938
                && $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
939
                    ? EEH_Template::get_button_or_link(
940
                        EE_Admin_Page::add_query_args_and_nonce(
941
                            array(
942
                                'action'      => 'send_payment_reminder',
943
                                'TXN_ID'      => $this->_transaction->ID(),
944
                                'redirect_to' => 'view_transaction',
945
                            ),
946
                            TXN_ADMIN_URL
947
                        ),
948
                        esc_html__(' Send Payment Reminder', 'event_espresso'),
949
                        'button secondary-button',
950
                        'dashicons dashicons-email-alt'
951
                    )
952
                    : '';
953
        }
954
955 View Code Duplication
        if (EE_Registry::instance()->CAP->current_user_can(
956
            'ee_edit_payments',
957
            'espresso_transactions_recalculate_line_items'
958
        )
959
        ) {
960
            $actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
961
                EE_Admin_Page::add_query_args_and_nonce(
962
                    array(
963
                        'action'      => 'espresso_recalculate_line_items',
964
                        'TXN_ID'      => $this->_transaction->ID(),
965
                        'redirect_to' => 'view_transaction',
966
                    ),
967
                    TXN_ADMIN_URL
968
                ),
969
                esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
970
                'button secondary-button',
971
                'dashicons dashicons-update'
972
            );
973
        }
974
975 View Code Duplication
        if ($primary_registration instanceof EE_Registration
976
            && EEH_MSG_Template::is_mt_active('receipt')
977
        ) {
978
            $actions['receipt'] = EEH_Template::get_button_or_link(
979
                $primary_registration->receipt_url(),
980
                esc_html__('View Receipt', 'event_espresso'),
981
                'button secondary-button',
982
                'dashicons dashicons-media-default'
983
            );
984
        }
985
986 View Code Duplication
        if ($primary_registration instanceof EE_Registration
987
            && EEH_MSG_Template::is_mt_active('invoice')
988
        ) {
989
            $actions['invoice'] = EEH_Template::get_button_or_link(
990
                $primary_registration->invoice_url(),
991
                esc_html__('View Invoice', 'event_espresso'),
992
                'button secondary-button',
993
                'dashicons dashicons-media-spreadsheet'
994
            );
995
        }
996
        $actions = array_filter(
997
            apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
998
        );
999
        if ($actions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $actions of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1000
            $content = '<ul>';
1001
            $content .= '<li>' . implode('</li><li>', $actions) . '</li>';
1002
            $content .= '</uL>';
1003
        }
1004
        return $content;
1005
    }
1006
1007
1008
    /**
1009
     * txn_details_meta_box
1010
     * generates HTML for the Transaction main meta box
1011
     *
1012
     * @return void
1013
     * @throws DomainException
1014
     * @throws EE_Error
1015
     * @throws InvalidArgumentException
1016
     * @throws InvalidDataTypeException
1017
     * @throws InvalidInterfaceException
1018
     * @throws RuntimeException
1019
     * @throws ReflectionException
1020
     */
1021
    public function txn_details_meta_box()
1022
    {
1023
        $this->_set_transaction_object();
1024
        $this->_template_args['TXN_ID'] = $this->_transaction->ID();
1025
        $this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration
1026
            ? $this->_transaction->primary_registration()->attendee()
1027
            : null;
1028
        $this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can(
1029
            'ee_edit_payments',
1030
            'apply_payment_or_refund_from_registration_details'
1031
        );
1032
        $this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
1033
            'ee_delete_payments',
1034
            'delete_payment_from_registration_details'
1035
        );
1036
1037
        // get line table
1038
        EEH_Autoloader::register_line_item_display_autoloaders();
1039
        $Line_Item_Display = new EE_Line_Item_Display(
1040
            'admin_table',
1041
            'EE_Admin_Table_Line_Item_Display_Strategy'
1042
        );
1043
        $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1044
            $this->_transaction->total_line_item()
1045
        );
1046
        $this->_template_args['REG_code'] = $this->_transaction->primary_registration()->reg_code();
1047
1048
        // process taxes
1049
        $taxes = $this->_transaction->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1050
        $this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
1051
1052
        $this->_template_args['grand_total'] = EEH_Template::format_currency(
1053
            $this->_transaction->total(),
1054
            false,
1055
            false
1056
        );
1057
        $this->_template_args['grand_raw_total'] = $this->_transaction->total();
1058
        $this->_template_args['TXN_status'] = $this->_transaction->status_ID();
1059
1060
        // process payment details
1061
        $payments = $this->_transaction->payments();
1062
        if (! empty($payments)) {
1063
            $this->_template_args['payments'] = $payments;
1064
            $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1065
        } else {
1066
            $this->_template_args['payments'] = false;
1067
            $this->_template_args['existing_reg_payments'] = array();
1068
        }
1069
1070
        $this->_template_args['edit_payment_url'] = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
1071
        $this->_template_args['delete_payment_url'] = add_query_arg(
1072
            array('action' => 'espresso_delete_payment'),
1073
            TXN_ADMIN_URL
1074
        );
1075
1076
        if (isset($txn_details['invoice_number'])) {
0 ignored issues
show
Bug introduced by
The variable $txn_details seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
1077
            $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1078
            $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1079
                'Invoice Number',
1080
                'event_espresso'
1081
            );
1082
        }
1083
1084
        $this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction
1085
            ->primary_registration()
1086
            ->session_ID();
1087
        $this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1088
            'Registration Session',
1089
            'event_espresso'
1090
        );
1091
1092
        $this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address'])
1093
            ? $this->_session['ip_address']
1094
            : '';
1095
        $this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1096
            'Transaction placed from IP',
1097
            'event_espresso'
1098
        );
1099
1100
        $this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent'])
1101
            ? $this->_session['user_agent']
1102
            : '';
1103
        $this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1104
            'Registrant User Agent',
1105
            'event_espresso'
1106
        );
1107
1108
        $reg_steps = '<ul>';
1109
        foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1110
            if ($reg_step_status === true) {
1111
                $reg_steps .= '<li style="color:#70cc50">'
1112
                              . sprintf(
1113
                                  esc_html__('%1$s : Completed', 'event_espresso'),
1114
                                  ucwords(str_replace('_', ' ', $reg_step))
1115
                              )
1116
                              . '</li>';
1117
            } elseif (is_numeric($reg_step_status) && $reg_step_status !== false) {
1118
                $reg_steps .= '<li style="color:#2EA2CC">'
1119
                              . sprintf(
1120
                                  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1121
                                  ucwords(str_replace('_', ' ', $reg_step)),
1122
                                  date(
1123
                                      get_option('date_format') . ' ' . get_option('time_format'),
1124
                                      $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1125
                                  )
1126
                              )
1127
                              . '</li>';
1128
            } else {
1129
                $reg_steps .= '<li style="color:#E76700">'
1130
                              . sprintf(
1131
                                  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1132
                                  ucwords(str_replace('_', ' ', $reg_step))
1133
                              )
1134
                              . '</li>';
1135
            }
1136
        }
1137
        $reg_steps .= '</ul>';
1138
        $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1139
        $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1140
            'Registration Step Progress',
1141
            'event_espresso'
1142
        );
1143
1144
1145
        $this->_get_registrations_to_apply_payment_to();
1146
        $this->_get_payment_methods($payments);
1147
        $this->_get_payment_status_array();
1148
        $this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1149
1150
        $this->_template_args['transaction_form_url'] = add_query_arg(
1151
            array(
1152
                'action'  => 'edit_transaction',
1153
                'process' => 'transaction',
1154
            ),
1155
            TXN_ADMIN_URL
1156
        );
1157
        $this->_template_args['apply_payment_form_url'] = add_query_arg(
1158
            array(
1159
                'page'   => 'espresso_transactions',
1160
                'action' => 'espresso_apply_payment',
1161
            ),
1162
            WP_AJAX_URL
1163
        );
1164
        $this->_template_args['delete_payment_form_url'] = add_query_arg(
1165
            array(
1166
                'page'   => 'espresso_transactions',
1167
                'action' => 'espresso_delete_payment',
1168
            ),
1169
            WP_AJAX_URL
1170
        );
1171
1172
        $this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1173
1174
        // 'espresso_delete_payment_nonce'
1175
1176
        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1177
        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1178
    }
1179
1180
1181
    /**
1182
     * _get_registration_payment_IDs
1183
     *    generates an array of Payment IDs and their corresponding Registration IDs
1184
     *
1185
     * @access protected
1186
     * @param EE_Payment[] $payments
1187
     * @return array
1188
     * @throws EE_Error
1189
     * @throws InvalidArgumentException
1190
     * @throws InvalidDataTypeException
1191
     * @throws InvalidInterfaceException
1192
     * @throws ReflectionException
1193
     */
1194
    protected function _get_registration_payment_IDs($payments = array())
1195
    {
1196
        $existing_reg_payments = array();
1197
        // get all reg payments for these payments
1198
        $reg_payments = EEM_Registration_Payment::instance()->get_all(
1199
            array(
1200
                array(
1201
                    'PAY_ID' => array(
1202
                        'IN',
1203
                        array_keys($payments),
1204
                    ),
1205
                ),
1206
            )
1207
        );
1208
        if (! empty($reg_payments)) {
1209
            foreach ($payments as $payment) {
1210
                if (! $payment instanceof EE_Payment) {
1211
                    continue;
1212
                } elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1213
                    $existing_reg_payments[ $payment->ID() ] = array();
1214
                }
1215
                foreach ($reg_payments as $reg_payment) {
1216
                    if ($reg_payment instanceof EE_Registration_Payment
1217
                        && $reg_payment->payment_ID() === $payment->ID()
1218
                    ) {
1219
                        $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1220
                    }
1221
                }
1222
            }
1223
        }
1224
1225
        return $existing_reg_payments;
1226
    }
1227
1228
1229
    /**
1230
     * _get_registrations_to_apply_payment_to
1231
     *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1232
     * which allows the admin to only apply the payment to the specific registrations
1233
     *
1234
     * @access protected
1235
     * @return void
1236
     * @throws EE_Error
1237
     * @throws InvalidArgumentException
1238
     * @throws InvalidDataTypeException
1239
     * @throws InvalidInterfaceException
1240
     * @throws ReflectionException
1241
     */
1242
    protected function _get_registrations_to_apply_payment_to()
1243
    {
1244
        // we want any registration with an active status (ie: not deleted or cancelled)
1245
        $query_params = array(
1246
            array(
1247
                'STS_ID' => array(
1248
                    'IN',
1249
                    array(
1250
                        EEM_Registration::status_id_approved,
1251
                        EEM_Registration::status_id_pending_payment,
1252
                        EEM_Registration::status_id_not_approved,
1253
                    ),
1254
                ),
1255
            ),
1256
        );
1257
        $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1258
            '',
1259
            'txn-admin-apply-payment-to-registrations-dv',
1260
            '',
1261
            'clear: both; margin: 1.5em 0 0; display: none;'
1262
        );
1263
        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1264
        $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1265
        $registrations_to_apply_payment_to .= EEH_HTML::thead(
1266
            EEH_HTML::tr(
1267
                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1268
                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1269
                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1270
                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1271
                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1272
                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1273
                EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1274
            )
1275
        );
1276
        $registrations_to_apply_payment_to .= EEH_HTML::tbody();
1277
        // get registrations for TXN
1278
        $registrations = $this->_transaction->registrations($query_params);
1279
        $existing_reg_payments = $this->_template_args['existing_reg_payments'];
1280
        foreach ($registrations as $registration) {
1281
            if ($registration instanceof EE_Registration) {
1282
                $attendee_name = $registration->attendee() instanceof EE_Attendee
1283
                    ? $registration->attendee()->full_name()
1284
                    : esc_html__('Unknown Attendee', 'event_espresso');
1285
                $owing = $registration->final_price() - $registration->paid();
1286
                $taxable = $registration->ticket()->taxable()
1287
                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1288
                    : '';
1289
                $checked = empty($existing_reg_payments)
1290
                           || in_array($registration->ID(), $existing_reg_payments, true)
1291
                    ? ' checked="checked"'
1292
                    : '';
1293
                $disabled = $registration->final_price() > 0 ? '' : ' disabled';
1294
                $registrations_to_apply_payment_to .= EEH_HTML::tr(
1295
                    EEH_HTML::td($registration->ID()) .
1296
                    EEH_HTML::td($attendee_name) .
1297
                    EEH_HTML::td(
1298
                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1299
                    ) .
1300
                    EEH_HTML::td($registration->event_name()) .
1301
                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1302
                    EEH_HTML::td(
1303
                        EEH_Template::format_currency($owing),
1304
                        '',
1305
                        'txn-admin-payment-owing-td jst-cntr'
1306
                    ) .
1307
                    EEH_HTML::td(
1308
                        '<input type="checkbox" value="' . $registration->ID()
1309
                        . '" name="txn_admin_payment[registrations]"'
1310
                        . $checked . $disabled . '>',
1311
                        '',
1312
                        'jst-cntr'
1313
                    ),
1314
                    'apply-payment-registration-row-' . $registration->ID()
1315
                );
1316
            }
1317
        }
1318
        $registrations_to_apply_payment_to .= EEH_HTML::tbodyx();
1319
        $registrations_to_apply_payment_to .= EEH_HTML::tablex();
1320
        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1321
        $registrations_to_apply_payment_to .= EEH_HTML::p(
1322
            esc_html__(
1323
                '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.',
1324
                'event_espresso'
1325
            ),
1326
            '',
1327
            'clear description'
1328
        );
1329
        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1330
        $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1331
    }
1332
1333
1334
    /**
1335
     * _get_reg_status_selection
1336
     *
1337
     * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1338
     *         instead of events.
1339
     * @access protected
1340
     * @return void
1341
     * @throws EE_Error
1342
     */
1343
    protected function _get_reg_status_selection()
1344
    {
1345
        // first get all possible statuses
1346
        $statuses = EEM_Registration::reg_status_array(array(), true);
1347
        // let's add a "don't change" option.
1348
        $status_array['NAN'] = esc_html__('Leave the Same', 'event_espresso');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$status_array was never initialized. Although not strictly required by PHP, it is generally a good practice to add $status_array = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1349
        $status_array = array_merge($status_array, $statuses);
1350
        $this->_template_args['status_change_select'] = EEH_Form_Fields::select_input(
1351
            'txn_reg_status_change[reg_status]',
1352
            $status_array,
1353
            'NAN',
1354
            'id="txn-admin-payment-reg-status-inp"',
1355
            'txn-reg-status-change-reg-status'
1356
        );
1357
        $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1358
            'delete_txn_reg_status_change[reg_status]',
1359
            $status_array,
1360
            'NAN',
1361
            'delete-txn-admin-payment-reg-status-inp',
1362
            'delete-txn-reg-status-change-reg-status'
1363
        );
1364
    }
1365
1366
1367
    /**
1368
     *    _get_payment_methods
1369
     * Gets all the payment methods available generally, or the ones that are already
1370
     * selected on these payments (in case their payment methods are no longer active).
1371
     * Has the side-effect of updating the template args' payment_methods item
1372
     *
1373
     * @access private
1374
     * @param EE_Payment[] to show on this page
1375
     * @return void
1376
     * @throws EE_Error
1377
     * @throws InvalidArgumentException
1378
     * @throws InvalidDataTypeException
1379
     * @throws InvalidInterfaceException
1380
     * @throws ReflectionException
1381
     */
1382
    private function _get_payment_methods($payments = array())
1383
    {
1384
        $payment_methods_of_payments = array();
1385
        foreach ($payments as $payment) {
1386
            if ($payment instanceof EE_Payment) {
1387
                $payment_methods_of_payments[] = $payment->ID();
1388
            }
1389
        }
1390
        if ($payment_methods_of_payments) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $payment_methods_of_payments of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1391
            $query_args = array(
1392
                array(
1393
                    'OR*payment_method_for_payment' => array(
1394
                        'PMD_ID'    => array('IN', $payment_methods_of_payments),
1395
                        'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1396
                    ),
1397
                ),
1398
            );
1399
        } else {
1400
            $query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1401
        }
1402
        $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1403
    }
1404
1405
1406
    /**
1407
     * txn_attendees_meta_box
1408
     *    generates HTML for the Attendees Transaction main meta box
1409
     *
1410
     * @access public
1411
     * @param WP_Post $post
1412
     * @param array   $metabox
1413
     * @return void
1414
     * @throws DomainException
1415
     * @throws EE_Error
1416
     * @throws InvalidArgumentException
1417
     * @throws InvalidDataTypeException
1418
     * @throws InvalidInterfaceException
1419
     * @throws ReflectionException
1420
     */
1421
    public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1422
    {
1423
1424
        /** @noinspection NonSecureExtractUsageInspection */
1425
        extract($metabox['args']);
1426
        $this->_template_args['post'] = $post;
1427
        $this->_template_args['event_attendees'] = array();
1428
        // process items in cart
1429
        $line_items = $this->_transaction->get_many_related(
1430
            'Line_Item',
1431
            array(array('LIN_type' => 'line-item'))
1432
        );
1433
        if (! empty($line_items)) {
1434
            foreach ($line_items as $item) {
1435
                if ($item instanceof EE_Line_Item) {
1436
                    switch ($item->OBJ_type()) {
1437
                        case 'Event':
1438
                            break;
1439
                        case 'Ticket':
1440
                            $ticket = $item->ticket();
1441
                            // right now we're only handling tickets here.
1442
                            // Cause its expected that only tickets will have attendees right?
1443
                            if (! $ticket instanceof EE_Ticket) {
1444
                                break;
1445
                            }
1446
                            try {
1447
                                $event_name = $ticket->get_event_name();
1448
                            } catch (Exception $e) {
1449
                                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1450
                                $event_name = esc_html__('Unknown Event', 'event_espresso');
1451
                            }
1452
                            $event_name .= ' - ' . $item->name();
1453
                            $ticket_price = EEH_Template::format_currency($item->unit_price());
1454
                            // now get all of the registrations for this transaction that use this ticket
1455
                            $registrations = $ticket->registrations(
1456
                                array(array('TXN_ID' => $this->_transaction->ID()))
1457
                            );
1458
                            foreach ($registrations as $registration) {
1459
                                if (! $registration instanceof EE_Registration) {
1460
                                    break;
1461
                                }
1462
                                $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1463
                                    = $registration->status_ID();
1464
                                $this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1465
                                    = $registration->count();
1466
                                $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1467
                                    = $event_name;
1468
                                $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1469
                                    = $ticket_price;
1470
                                // attendee info
1471
                                $attendee = $registration->get_first_related('Attendee');
1472
                                if ($attendee instanceof EE_Attendee) {
1473
                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1474
                                        = $attendee->ID();
1475
                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1476
                                        = $attendee->full_name();
1477
                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']
1478
                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1479
                                          . esc_html__(
1480
                                              ' Event',
1481
                                              'event_espresso'
1482
                                          )
1483
                                          . '">' . $attendee->email() . '</a>';
1484
                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']
1485
                                        = EEH_Address::format($attendee, 'inline', false, false);
1486
                                } else {
1487
                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] = '';
1488
                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1489
                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email'] = '';
1490
                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address'] = '';
1491
                                }
1492
                            }
1493
                            break;
1494
                    }
1495
                }
1496
            }
1497
1498
            $this->_template_args['transaction_form_url'] = add_query_arg(
1499
                array(
1500
                    'action'  => 'edit_transaction',
1501
                    'process' => 'attendees',
1502
                ),
1503
                TXN_ADMIN_URL
1504
            );
1505
            echo EEH_Template::display_template(
1506
                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1507
                $this->_template_args,
1508
                true
1509
            );
1510
        } else {
1511
            echo sprintf(
1512
                esc_html__(
1513
                    '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1514
                    'event_espresso'
1515
                ),
1516
                '<p class="important-notice">',
1517
                '</p>'
1518
            );
1519
        }
1520
    }
1521
1522
1523
    /**
1524
     * txn_registrant_side_meta_box
1525
     * generates HTML for the Edit Transaction side meta box
1526
     *
1527
     * @access public
1528
     * @return void
1529
     * @throws DomainException
1530
     * @throws EE_Error
1531
     * @throws InvalidArgumentException
1532
     * @throws InvalidDataTypeException
1533
     * @throws InvalidInterfaceException
1534
     * @throws ReflectionException
1535
     */
1536
    public function txn_registrant_side_meta_box()
1537
    {
1538
        $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1539
            ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1540
            : null;
1541
        if (! $primary_att instanceof EE_Attendee) {
1542
            $this->_template_args['no_attendee_message'] = esc_html__(
1543
                'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1544
                'event_espresso'
1545
            );
1546
            $primary_att = EEM_Attendee::instance()->create_default_object();
1547
        }
1548
        $this->_template_args['ATT_ID'] = $primary_att->ID();
1549
        $this->_template_args['prime_reg_fname'] = $primary_att->fname();
1550
        $this->_template_args['prime_reg_lname'] = $primary_att->lname();
1551
        $this->_template_args['prime_reg_email'] = $primary_att->email();
1552
        $this->_template_args['prime_reg_phone'] = $primary_att->phone();
1553
        $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1554
            array(
1555
                'action' => 'edit_attendee',
1556
                'post'   => $primary_att->ID(),
1557
            ),
1558
            REG_ADMIN_URL
1559
        );
1560
        // get formatted address for registrant
1561
        $this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1562
        echo EEH_Template::display_template(
1563
            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1564
            $this->_template_args,
1565
            true
1566
        );
1567
    }
1568
1569
1570
    /**
1571
     * txn_billing_info_side_meta_box
1572
     *    generates HTML for the Edit Transaction side meta box
1573
     *
1574
     * @access public
1575
     * @return void
1576
     * @throws DomainException
1577
     * @throws EE_Error
1578
     */
1579
    public function txn_billing_info_side_meta_box()
1580
    {
1581
1582
        $this->_template_args['billing_form'] = $this->_transaction->billing_info();
1583
        $this->_template_args['billing_form_url'] = add_query_arg(
1584
            array('action' => 'edit_transaction', 'process' => 'billing'),
1585
            TXN_ADMIN_URL
1586
        );
1587
1588
        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1589
        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1590
    }
1591
1592
1593
    /**
1594
     * apply_payments_or_refunds
1595
     *    registers a payment or refund made towards a transaction
1596
     *
1597
     * @access public
1598
     * @return void
1599
     * @throws EE_Error
1600
     * @throws InvalidArgumentException
1601
     * @throws ReflectionException
1602
     * @throws RuntimeException
1603
     * @throws InvalidDataTypeException
1604
     * @throws InvalidInterfaceException
1605
     */
1606
    public function apply_payments_or_refunds()
1607
    {
1608
        $json_response_data = array('return_data' => false);
1609
        $valid_data = $this->_validate_payment_request_data();
1610
        $has_access = EE_Registry::instance()->CAP->current_user_can(
1611
            'ee_edit_payments',
1612
            'apply_payment_or_refund_from_registration_details'
1613
        );
1614
        if (! empty($valid_data) && $has_access) {
1615
            $PAY_ID = $valid_data['PAY_ID'];
1616
            // save  the new payment
1617
            $payment = $this->_create_payment_from_request_data($valid_data);
1618
            // get the TXN for this payment
1619
            $transaction = $payment->transaction();
1620
            // verify transaction
1621
            if ($transaction instanceof EE_Transaction) {
1622
                // calculate_total_payments_and_update_status
1623
                $this->_process_transaction_payments($transaction);
1624
                $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1625
                $this->_remove_existing_registration_payments($payment, $PAY_ID);
1626
                // apply payment to registrations (if applicable)
1627
                if (! empty($REG_IDs)) {
1628
                    $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1629
                    $this->_maybe_send_notifications();
1630
                    // now process status changes for the same registrations
1631
                    $this->_process_registration_status_change($transaction, $REG_IDs);
1632
                }
1633
                $this->_maybe_send_notifications($payment);
1634
                // prepare to render page
1635
                $json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1636
                do_action(
1637
                    'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1638
                    $transaction,
1639
                    $payment
1640
                );
1641
            } else {
1642
                EE_Error::add_error(
1643
                    esc_html__(
1644
                        'A valid Transaction for this payment could not be retrieved.',
1645
                        'event_espresso'
1646
                    ),
1647
                    __FILE__,
1648
                    __FUNCTION__,
1649
                    __LINE__
1650
                );
1651
            }
1652
        } elseif ($has_access) {
1653
            EE_Error::add_error(
1654
                esc_html__(
1655
                    'The payment form data could not be processed. Please try again.',
1656
                    'event_espresso'
1657
                ),
1658
                __FILE__,
1659
                __FUNCTION__,
1660
                __LINE__
1661
            );
1662
        } else {
1663
            EE_Error::add_error(
1664
                esc_html__(
1665
                    'You do not have access to apply payments or refunds to a registration.',
1666
                    'event_espresso'
1667
                ),
1668
                __FILE__,
1669
                __FUNCTION__,
1670
                __LINE__
1671
            );
1672
        }
1673
        $notices = EE_Error::get_notices(
1674
            false,
1675
            false,
1676
            false
1677
        );
1678
        $this->_template_args = array(
1679
            'data'    => $json_response_data,
1680
            'error'   => $notices['errors'],
1681
            'success' => $notices['success'],
1682
        );
1683
        $this->_return_json();
1684
    }
1685
1686
1687
    /**
1688
     * _validate_payment_request_data
1689
     *
1690
     * @return array
1691
     * @throws EE_Error
1692
     * @throws InvalidArgumentException
1693
     * @throws InvalidDataTypeException
1694
     * @throws InvalidInterfaceException
1695
     */
1696
    protected function _validate_payment_request_data()
1697
    {
1698
        if (! isset($this->_req_data['txn_admin_payment'])) {
1699
            return array();
1700
        }
1701
        $payment_form = $this->_generate_payment_form_section();
1702
        try {
1703
            if ($payment_form->was_submitted()) {
1704
                $payment_form->receive_form_submission();
1705
                if (! $payment_form->is_valid()) {
1706
                    $submission_error_messages = array();
1707
                    foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1708
                        if ($validation_error instanceof EE_Validation_Error) {
1709
                            $submission_error_messages[] = sprintf(
1710
                                _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1711
                                $validation_error->get_form_section()->html_label_text(),
1712
                                $validation_error->getMessage()
1713
                            );
1714
                        }
1715
                    }
1716
                    EE_Error::add_error(
1717
                        implode('<br />', $submission_error_messages),
1718
                        __FILE__,
1719
                        __FUNCTION__,
1720
                        __LINE__
1721
                    );
1722
                    return array();
1723
                }
1724
            }
1725
        } catch (EE_Error $e) {
1726
            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1727
            return array();
1728
        }
1729
1730
        return $payment_form->valid_data();
1731
    }
1732
1733
1734
    /**
1735
     * _generate_payment_form_section
1736
     *
1737
     * @return EE_Form_Section_Proper
1738
     * @throws EE_Error
1739
     */
1740
    protected function _generate_payment_form_section()
1741
    {
1742
        return new EE_Form_Section_Proper(
1743
            array(
1744
                'name'        => 'txn_admin_payment',
1745
                'subsections' => array(
1746
                    'PAY_ID'          => new EE_Text_Input(
1747
                        array(
1748
                            'default'               => 0,
1749
                            'required'              => false,
1750
                            'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1751
                            'validation_strategies' => array(new EE_Int_Normalization()),
1752
                        )
1753
                    ),
1754
                    'TXN_ID'          => new EE_Text_Input(
1755
                        array(
1756
                            'default'               => 0,
1757
                            'required'              => true,
1758
                            'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1759
                            'validation_strategies' => array(new EE_Int_Normalization()),
1760
                        )
1761
                    ),
1762
                    'type'            => new EE_Text_Input(
1763
                        array(
1764
                            'default'               => 1,
1765
                            'required'              => true,
1766
                            'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1767
                            'validation_strategies' => array(new EE_Int_Normalization()),
1768
                        )
1769
                    ),
1770
                    'amount'          => new EE_Text_Input(
1771
                        array(
1772
                            'default'               => 0,
1773
                            'required'              => true,
1774
                            'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1775
                            'validation_strategies' => array(new EE_Float_Normalization()),
1776
                        )
1777
                    ),
1778
                    'status'          => new EE_Text_Input(
1779
                        array(
1780
                            'default'         => EEM_Payment::status_id_approved,
1781
                            'required'        => true,
1782
                            'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1783
                        )
1784
                    ),
1785
                    'PMD_ID'          => new EE_Text_Input(
1786
                        array(
1787
                            'default'               => 2,
1788
                            'required'              => true,
1789
                            'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1790
                            'validation_strategies' => array(new EE_Int_Normalization()),
1791
                        )
1792
                    ),
1793
                    'date'            => new EE_Text_Input(
1794
                        array(
1795
                            'default'         => time(),
1796
                            'required'        => true,
1797
                            'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1798
                        )
1799
                    ),
1800
                    'txn_id_chq_nmbr' => new EE_Text_Input(
1801
                        array(
1802
                            'default'               => '',
1803
                            'required'              => false,
1804
                            'html_label_text'       => esc_html__('Transaction or Cheque 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
                    'po_number'       => new EE_Text_Input(
1814
                        array(
1815
                            'default'               => '',
1816
                            'required'              => false,
1817
                            'html_label_text'       => esc_html__('Purchase Order Number', '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
                    'accounting'      => new EE_Text_Input(
1827
                        array(
1828
                            'default'               => '',
1829
                            'required'              => false,
1830
                            'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1831
                            'validation_strategies' => array(
1832
                                new EE_Max_Length_Validation_Strategy(
1833
                                    esc_html__('Input too long', 'event_espresso'),
1834
                                    100
1835
                                ),
1836
                            ),
1837
                        )
1838
                    ),
1839
                ),
1840
            )
1841
        );
1842
    }
1843
1844
1845
    /**
1846
     * _create_payment_from_request_data
1847
     *
1848
     * @param array $valid_data
1849
     * @return EE_Payment
1850
     * @throws EE_Error
1851
     * @throws InvalidArgumentException
1852
     * @throws InvalidDataTypeException
1853
     * @throws InvalidInterfaceException
1854
     * @throws ReflectionException
1855
     */
1856
    protected function _create_payment_from_request_data($valid_data)
1857
    {
1858
        $PAY_ID = $valid_data['PAY_ID'];
1859
        // get payment amount
1860
        $amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1861
        // payments have a type value of 1 and refunds have a type value of -1
1862
        // so multiplying amount by type will give a positive value for payments, and negative values for refunds
1863
        $amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1864
        // for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1865
        $date = $valid_data['date']
1866
            ? preg_replace('/\s+/', ' ', $valid_data['date'])
1867
            : date('Y-m-d g:i a', current_time('timestamp'));
1868
        $payment = EE_Payment::new_instance(
1869
            array(
1870
                'TXN_ID'              => $valid_data['TXN_ID'],
1871
                'STS_ID'              => $valid_data['status'],
1872
                'PAY_timestamp'       => $date,
1873
                'PAY_source'          => EEM_Payment_Method::scope_admin,
1874
                'PMD_ID'              => $valid_data['PMD_ID'],
1875
                'PAY_amount'          => $amount,
1876
                'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1877
                'PAY_po_number'       => $valid_data['po_number'],
1878
                'PAY_extra_accntng'   => $valid_data['accounting'],
1879
                'PAY_details'         => $valid_data,
1880
                'PAY_ID'              => $PAY_ID,
1881
            ),
1882
            '',
1883
            array('Y-m-d', 'g:i a')
1884
        );
1885
1886
        if (! $payment->save()) {
1887
            EE_Error::add_error(
1888
                sprintf(
1889
                    esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1890
                    $payment->ID()
1891
                ),
1892
                __FILE__,
1893
                __FUNCTION__,
1894
                __LINE__
1895
            );
1896
        }
1897
1898
        return $payment;
1899
    }
1900
1901
1902
    /**
1903
     * _process_transaction_payments
1904
     *
1905
     * @param \EE_Transaction $transaction
1906
     * @return void
1907
     * @throws EE_Error
1908
     * @throws InvalidArgumentException
1909
     * @throws ReflectionException
1910
     * @throws InvalidDataTypeException
1911
     * @throws InvalidInterfaceException
1912
     */
1913
    protected function _process_transaction_payments(EE_Transaction $transaction)
1914
    {
1915
        /** @type EE_Transaction_Payments $transaction_payments */
1916
        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1917
        // update the transaction with this payment
1918 View Code Duplication
        if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1919
            EE_Error::add_success(
1920
                esc_html__(
1921
                    'The payment has been processed successfully.',
1922
                    'event_espresso'
1923
                ),
1924
                __FILE__,
1925
                __FUNCTION__,
1926
                __LINE__
1927
            );
1928
        } else {
1929
            EE_Error::add_error(
1930
                esc_html__(
1931
                    'The payment was processed successfully but the amount paid for the transaction was not updated.',
1932
                    'event_espresso'
1933
                ),
1934
                __FILE__,
1935
                __FUNCTION__,
1936
                __LINE__
1937
            );
1938
        }
1939
    }
1940
1941
1942
    /**
1943
     * _get_REG_IDs_to_apply_payment_to
1944
     * returns a list of registration IDs that the payment will apply to
1945
     *
1946
     * @param \EE_Payment $payment
1947
     * @return array
1948
     * @throws EE_Error
1949
     * @throws InvalidArgumentException
1950
     * @throws InvalidDataTypeException
1951
     * @throws InvalidInterfaceException
1952
     * @throws ReflectionException
1953
     */
1954
    protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1955
    {
1956
        $REG_IDs = array();
1957
        // grab array of IDs for specific registrations to apply changes to
1958
        if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1959
            $REG_IDs = (array) $this->_req_data['txn_admin_payment']['registrations'];
1960
        }
1961
        // nothing specified ? then get all reg IDs
1962
        if (empty($REG_IDs)) {
1963
            $registrations = $payment->transaction()->registrations();
1964
            $REG_IDs = ! empty($registrations)
1965
                ? array_keys($registrations)
1966
                : $this->_get_existing_reg_payment_REG_IDs($payment);
1967
        }
1968
1969
        // ensure that REG_IDs are integers and NOT strings
1970
        return array_map('intval', $REG_IDs);
1971
    }
1972
1973
1974
    /**
1975
     * @return array
1976
     */
1977
    public function existing_reg_payment_REG_IDs()
1978
    {
1979
        return $this->_existing_reg_payment_REG_IDs;
1980
    }
1981
1982
1983
    /**
1984
     * @param array $existing_reg_payment_REG_IDs
1985
     */
1986
    public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1987
    {
1988
        $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
0 ignored issues
show
Documentation Bug introduced by
It seems like $existing_reg_payment_REG_IDs can be null. However, the property $_existing_reg_payment_REG_IDs is declared as array. Maybe change the type of the property to array|null or add a type check?

Our type inference engine has found an assignment of a scalar value (like a string, an integer or null) to a property which is an array.

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

To type hint that a parameter can be either an array or null, you can set a type hint of array and a default value of null. The PHP interpreter will then accept both an array or null for that parameter.

function aContainsB(array $needle = null, array  $haystack) {
    if (!$needle) {
        return false;
    }

    return array_intersect($haystack, $needle) == $haystack;
}

The function can be called with either null or an array for the parameter $needle but will only accept an array as $haystack.

Loading history...
1989
    }
1990
1991
1992
    /**
1993
     * _get_existing_reg_payment_REG_IDs
1994
     * returns a list of registration IDs that the payment is currently related to
1995
     * as recorded in the database
1996
     *
1997
     * @param \EE_Payment $payment
1998
     * @return array
1999
     * @throws EE_Error
2000
     * @throws InvalidArgumentException
2001
     * @throws InvalidDataTypeException
2002
     * @throws InvalidInterfaceException
2003
     * @throws ReflectionException
2004
     */
2005
    protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
2006
    {
2007
        if ($this->existing_reg_payment_REG_IDs() === null) {
2008
            // let's get any existing reg payment records for this payment
2009
            $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2010
            // but we only want the REG IDs, so grab the array keys
2011
            $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2012
                ? array_keys($existing_reg_payment_REG_IDs)
2013
                : array();
2014
            $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2015
        }
2016
2017
        return $this->existing_reg_payment_REG_IDs();
2018
    }
2019
2020
2021
    /**
2022
     * _remove_existing_registration_payments
2023
     * this calculates the difference between existing relations
2024
     * to the supplied payment and the new list registration IDs,
2025
     * removes any related registrations that no longer apply,
2026
     * and then updates the registration paid fields
2027
     *
2028
     * @param \EE_Payment $payment
2029
     * @param int         $PAY_ID
2030
     * @return bool;
2031
     * @throws EE_Error
2032
     * @throws InvalidArgumentException
2033
     * @throws ReflectionException
2034
     * @throws InvalidDataTypeException
2035
     * @throws InvalidInterfaceException
2036
     */
2037
    protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2038
    {
2039
        // newly created payments will have nothing recorded for $PAY_ID
2040
        if (absint($PAY_ID) === 0) {
2041
            return false;
2042
        }
2043
        $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2044
        if (empty($existing_reg_payment_REG_IDs)) {
2045
            return false;
2046
        }
2047
        /** @type EE_Transaction_Payments $transaction_payments */
2048
        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2049
2050
        return $transaction_payments->delete_registration_payments_and_update_registrations(
2051
            $payment,
2052
            array(
2053
                array(
2054
                    'PAY_ID' => $payment->ID(),
2055
                    'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
2056
                ),
2057
            )
2058
        );
2059
    }
2060
2061
2062
    /**
2063
     * _update_registration_payments
2064
     * this applies the payments to the selected registrations
2065
     * but only if they have not already been paid for
2066
     *
2067
     * @param  EE_Transaction $transaction
2068
     * @param \EE_Payment     $payment
2069
     * @param array           $REG_IDs
2070
     * @return void
2071
     * @throws EE_Error
2072
     * @throws InvalidArgumentException
2073
     * @throws ReflectionException
2074
     * @throws RuntimeException
2075
     * @throws InvalidDataTypeException
2076
     * @throws InvalidInterfaceException
2077
     */
2078
    protected function _update_registration_payments(
2079
        EE_Transaction $transaction,
2080
        EE_Payment $payment,
2081
        $REG_IDs = array()
2082
    ) {
2083
        // we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2084
        // so let's do that using our set of REG_IDs from the form
2085
        $registration_query_where_params = array(
2086
            'REG_ID' => array('IN', $REG_IDs),
2087
        );
2088
        // but add in some conditions regarding payment,
2089
        // so that we don't apply payments to registrations that are free or have already been paid for
2090
        // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2091
        if (! $payment->is_a_refund()) {
2092
            $registration_query_where_params['REG_final_price'] = array('!=', 0);
2093
            $registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
2094
        }
2095
        $registrations = $transaction->registrations(array($registration_query_where_params));
2096
        if (! empty($registrations)) {
2097
            /** @type EE_Payment_Processor $payment_processor */
2098
            $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2099
            $payment_processor->process_registration_payments($transaction, $payment, $registrations);
2100
        }
2101
    }
2102
2103
2104
    /**
2105
     * _process_registration_status_change
2106
     * This processes requested registration status changes for all the registrations
2107
     * on a given transaction and (optionally) sends out notifications for the changes.
2108
     *
2109
     * @param  EE_Transaction $transaction
2110
     * @param array           $REG_IDs
2111
     * @return bool
2112
     * @throws EE_Error
2113
     * @throws InvalidArgumentException
2114
     * @throws ReflectionException
2115
     * @throws InvalidDataTypeException
2116
     * @throws InvalidInterfaceException
2117
     */
2118
    protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
2119
    {
2120
        // first if there is no change in status then we get out.
2121
        if (! isset($this->_req_data['txn_reg_status_change']['reg_status'])
2122
            || $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN'
2123
        ) {
2124
            // no error message, no change requested, just nothing to do man.
2125
            return false;
2126
        }
2127
        /** @type EE_Transaction_Processor $transaction_processor */
2128
        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2129
2130
        // made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2131
        return $transaction_processor->manually_update_registration_statuses(
2132
            $transaction,
2133
            sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
2134
            array(array('REG_ID' => array('IN', $REG_IDs)))
2135
        );
2136
    }
2137
2138
2139
    /**
2140
     * _build_payment_json_response
2141
     *
2142
     * @access public
2143
     * @param \EE_Payment $payment
2144
     * @param array       $REG_IDs
2145
     * @param bool | null $delete_txn_reg_status_change
2146
     * @return array
2147
     * @throws EE_Error
2148
     * @throws InvalidArgumentException
2149
     * @throws InvalidDataTypeException
2150
     * @throws InvalidInterfaceException
2151
     * @throws ReflectionException
2152
     */
2153
    protected function _build_payment_json_response(
2154
        EE_Payment $payment,
2155
        $REG_IDs = array(),
2156
        $delete_txn_reg_status_change = null
2157
    ) {
2158
        // was the payment deleted ?
2159
        if (is_bool($delete_txn_reg_status_change)) {
2160
            return array(
2161
                'PAY_ID'                       => $payment->ID(),
2162
                'amount'                       => $payment->amount(),
2163
                'total_paid'                   => $payment->transaction()->paid(),
2164
                'txn_status'                   => $payment->transaction()->status_ID(),
2165
                'pay_status'                   => $payment->STS_ID(),
2166
                'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2167
                'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2168
            );
2169
        } else {
2170
            $this->_get_payment_status_array();
2171
2172
            return array(
2173
                'amount'           => $payment->amount(),
2174
                'total_paid'       => $payment->transaction()->paid(),
2175
                'txn_status'       => $payment->transaction()->status_ID(),
2176
                'pay_status'       => $payment->STS_ID(),
2177
                'PAY_ID'           => $payment->ID(),
2178
                'STS_ID'           => $payment->STS_ID(),
2179
                'status'           => self::$_pay_status[ $payment->STS_ID() ],
2180
                'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2181
                'method'           => strtoupper($payment->source()),
2182
                'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2183
                'gateway'          => $payment->payment_method()
2184
                    ? $payment->payment_method()->admin_name()
2185
                    : esc_html__('Unknown', 'event_espresso'),
2186
                'gateway_response' => $payment->gateway_response(),
2187
                'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2188
                'po_number'        => $payment->po_number(),
2189
                'extra_accntng'    => $payment->extra_accntng(),
2190
                'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2191
            );
2192
        }
2193
    }
2194
2195
2196
    /**
2197
     * delete_payment
2198
     *    delete a payment or refund made towards a transaction
2199
     *
2200
     * @access public
2201
     * @return void
2202
     * @throws EE_Error
2203
     * @throws InvalidArgumentException
2204
     * @throws ReflectionException
2205
     * @throws InvalidDataTypeException
2206
     * @throws InvalidInterfaceException
2207
     */
2208
    public function delete_payment()
2209
    {
2210
        $json_response_data = array('return_data' => false);
2211
        $PAY_ID = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2212
            ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2213
            : 0;
2214
        $can_delete = EE_Registry::instance()->CAP->current_user_can(
2215
            'ee_delete_payments',
2216
            'delete_payment_from_registration_details'
2217
        );
2218
        if ($PAY_ID && $can_delete) {
2219
            $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change'])
2220
                ? $this->_req_data['delete_txn_reg_status_change']
2221
                : false;
2222
            $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2223
            if ($payment instanceof EE_Payment) {
2224
                $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2225
                /** @type EE_Transaction_Payments $transaction_payments */
2226
                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2227
                if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2228
                    $json_response_data['return_data'] = $this->_build_payment_json_response(
2229
                        $payment,
2230
                        $REG_IDs,
2231
                        $delete_txn_reg_status_change
2232
                    );
2233
                    if ($delete_txn_reg_status_change) {
2234
                        $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
2235
                        // MAKE sure we also add the delete_txn_req_status_change to the
2236
                        // $_REQUEST global because that's how messages will be looking for it.
2237
                        $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
2238
                        $this->_maybe_send_notifications();
2239
                        $this->_process_registration_status_change($payment->transaction(), $REG_IDs);
0 ignored issues
show
Bug introduced by
It seems like $payment->transaction() can be null; however, _process_registration_status_change() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
2240
                    }
2241
                }
2242
            } else {
2243
                EE_Error::add_error(
2244
                    esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2245
                    __FILE__,
2246
                    __FUNCTION__,
2247
                    __LINE__
2248
                );
2249
            }
2250
        } elseif ($can_delete) {
2251
            EE_Error::add_error(
2252
                esc_html__(
2253
                    'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2254
                    'event_espresso'
2255
                ),
2256
                __FILE__,
2257
                __FUNCTION__,
2258
                __LINE__
2259
            );
2260
        } else {
2261
            EE_Error::add_error(
2262
                esc_html__(
2263
                    'You do not have access to delete a payment.',
2264
                    'event_espresso'
2265
                ),
2266
                __FILE__,
2267
                __FUNCTION__,
2268
                __LINE__
2269
            );
2270
        }
2271
        $notices = EE_Error::get_notices(false, false, false);
2272
        $this->_template_args = array(
2273
            'data'      => $json_response_data,
2274
            'success'   => $notices['success'],
2275
            'error'     => $notices['errors'],
2276
            'attention' => $notices['attention'],
2277
        );
2278
        $this->_return_json();
2279
    }
2280
2281
2282
    /**
2283
     * _registration_payment_data_array
2284
     * adds info for 'owing' and 'paid' for each registration to the json response
2285
     *
2286
     * @access protected
2287
     * @param array $REG_IDs
2288
     * @return array
2289
     * @throws EE_Error
2290
     * @throws InvalidArgumentException
2291
     * @throws InvalidDataTypeException
2292
     * @throws InvalidInterfaceException
2293
     * @throws ReflectionException
2294
     */
2295
    protected function _registration_payment_data_array($REG_IDs)
2296
    {
2297
        $registration_payment_data = array();
2298
        // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2299
        if (! empty($REG_IDs)) {
2300
            $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2301
            foreach ($registrations as $registration) {
2302
                if ($registration instanceof EE_Registration) {
2303
                    $registration_payment_data[ $registration->ID() ] = array(
2304
                        'paid'  => $registration->pretty_paid(),
2305
                        'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2306
                    );
2307
                }
2308
            }
2309
        }
2310
2311
        return $registration_payment_data;
2312
    }
2313
2314
2315
    /**
2316
     * _maybe_send_notifications
2317
     * determines whether or not the admin has indicated that notifications should be sent.
2318
     * If so, will toggle a filter switch for delivering registration notices.
2319
     * If passed an EE_Payment object, then it will trigger payment notifications instead.
2320
     *
2321
     * @access protected
2322
     * @param \EE_Payment | null $payment
2323
     */
2324
    protected function _maybe_send_notifications($payment = null)
2325
    {
2326
        switch ($payment instanceof EE_Payment) {
2327
            // payment notifications
2328 View Code Duplication
            case true:
2329
                if (isset($this->_req_data['txn_payments']['send_notifications'])
2330
                    && filter_var(
2331
                        $this->_req_data['txn_payments']['send_notifications'],
2332
                        FILTER_VALIDATE_BOOLEAN
2333
                    )
2334
                ) {
2335
                    $this->_process_payment_notification($payment);
2336
                }
2337
                break;
2338
            // registration notifications
2339 View Code Duplication
            case false:
2340
                if (isset($this->_req_data['txn_reg_status_change']['send_notifications'])
2341
                    && filter_var(
2342
                        $this->_req_data['txn_reg_status_change']['send_notifications'],
2343
                        FILTER_VALIDATE_BOOLEAN
2344
                    )
2345
                ) {
2346
                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2347
                }
2348
                break;
2349
        }
2350
    }
2351
2352
2353
    /**
2354
     * _send_payment_reminder
2355
     *    generates HTML for the View Transaction Details Admin page
2356
     *
2357
     * @access protected
2358
     * @return void
2359
     * @throws EE_Error
2360
     * @throws InvalidArgumentException
2361
     * @throws InvalidDataTypeException
2362
     * @throws InvalidInterfaceException
2363
     */
2364
    protected function _send_payment_reminder()
2365
    {
2366
        $TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2367
        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2368
        $query_args = isset($this->_req_data['redirect_to']) ? array(
2369
            'action' => $this->_req_data['redirect_to'],
2370
            'TXN_ID' => $this->_req_data['TXN_ID'],
2371
        ) : array();
2372
        do_action(
2373
            'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2374
            $transaction
2375
        );
2376
        $this->_redirect_after_action(
2377
            false,
2378
            esc_html__('payment reminder', 'event_espresso'),
2379
            esc_html__('sent', 'event_espresso'),
2380
            $query_args,
2381
            true
2382
        );
2383
    }
2384
2385
2386
    /**
2387
     *  get_transactions
2388
     *    get transactions for given parameters (used by list table)
2389
     *
2390
     * @param  int     $perpage how many transactions displayed per page
2391
     * @param  boolean $count   return the count or objects
2392
     * @param string   $view
2393
     * @return mixed int = count || array of transaction objects
2394
     * @throws EE_Error
2395
     * @throws InvalidArgumentException
2396
     * @throws InvalidDataTypeException
2397
     * @throws InvalidInterfaceException
2398
     */
2399
    public function get_transactions($perpage, $count = false, $view = '')
2400
    {
2401
2402
        $TXN = EEM_Transaction::instance();
2403
2404
        $start_date = isset($this->_req_data['txn-filter-start-date'])
2405
            ? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
2406
            : date(
2407
                'm/d/Y',
2408
                strtotime('-10 year')
2409
            );
2410
        $end_date = isset($this->_req_data['txn-filter-end-date'])
2411
            ? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
2412
            : date('m/d/Y');
2413
2414
        // make sure our timestamps start and end right at the boundaries for each day
2415
        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2416
        $end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2417
2418
2419
        // convert to timestamps
2420
        $start_date = strtotime($start_date);
2421
        $end_date = strtotime($end_date);
2422
2423
        // makes sure start date is the lowest value and vice versa
2424
        $start_date = min($start_date, $end_date);
2425
        $end_date = max($start_date, $end_date);
2426
2427
        // convert to correct format for query
2428
        $start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2429
            'TXN_timestamp',
2430
            date('Y-m-d H:i:s', $start_date),
2431
            'Y-m-d H:i:s'
2432
        );
2433
        $end_date = EEM_Transaction::instance()->convert_datetime_for_query(
2434
            'TXN_timestamp',
2435
            date('Y-m-d H:i:s', $end_date),
2436
            'Y-m-d H:i:s'
2437
        );
2438
2439
2440
        // set orderby
2441
        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2442
2443
        switch ($this->_req_data['orderby']) {
2444
            case 'TXN_ID':
2445
                $orderby = 'TXN_ID';
2446
                break;
2447
            case 'ATT_fname':
2448
                $orderby = 'Registration.Attendee.ATT_fname';
2449
                break;
2450
            case 'event_name':
2451
                $orderby = 'Registration.Event.EVT_name';
2452
                break;
2453
            default: // 'TXN_timestamp'
2454
                $orderby = 'TXN_timestamp';
2455
        }
2456
2457
        $sort = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2458
        $current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
2459
        $per_page = ! empty($perpage) ? $perpage : 10;
2460
        $per_page = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
2461
2462
        $offset = ($current_page - 1) * $per_page;
2463
        $limit = array($offset, $per_page);
2464
2465
        $_where = array(
2466
            'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
2467
            'Registration.REG_count' => 1,
2468
        );
2469
2470
        if (isset($this->_req_data['EVT_ID'])) {
2471
            $_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
2472
        }
2473
2474
        if (isset($this->_req_data['s'])) {
2475
            $search_string = '%' . $this->_req_data['s'] . '%';
2476
            $_where['OR'] = array(
2477
                'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2478
                'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
2479
                'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
2480
                'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
2481
                'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
2482
                'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
2483
                'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
2484
                'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
2485
                'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
2486
                'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
2487
                'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
2488
                'Registration.REG_final_price'        => array('LIKE', $search_string),
2489
                'Registration.REG_code'               => array('LIKE', $search_string),
2490
                'Registration.REG_count'              => array('LIKE', $search_string),
2491
                'Registration.REG_group_size'         => array('LIKE', $search_string),
2492
                'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
2493
                'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
2494
                'Payment.PAY_source'                  => array('LIKE', $search_string),
2495
                'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
2496
                'TXN_session_data'                    => array('LIKE', $search_string),
2497
                'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string),
2498
            );
2499
        }
2500
2501
        // failed transactions
2502
        $failed = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2503
                  || ($count && $view === 'failed');
2504
        $abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2505
                     || ($count && $view === 'abandoned');
2506
        $incomplete = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count)
2507
                      || ($count && $view === 'incomplete');
2508
2509
        if ($failed) {
2510
            $_where['STS_ID'] = EEM_Transaction::failed_status_code;
2511
        } elseif ($abandoned) {
2512
            $_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2513
        } elseif ($incomplete) {
2514
            $_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2515
        } else {
2516
            $_where['STS_ID'] = array('!=', EEM_Transaction::failed_status_code);
2517
            $_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
2518
        }
2519
2520
        $query_params = apply_filters(
2521
            'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2522
            array(
2523
                $_where,
2524
                'order_by'                 => array($orderby => $sort),
2525
                'limit'                    => $limit,
2526
                'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2527
            ),
2528
            $this->_req_data,
2529
            $view,
2530
            $count
2531
        );
2532
2533
        $transactions = $count
2534
            ? $TXN->count(array($query_params[0]), 'TXN_ID', true)
2535
            : $TXN->get_all($query_params);
2536
2537
        return $transactions;
2538
    }
2539
2540
2541
    /**
2542
     * @since 4.9.79.p
2543
     * @throws EE_Error
2544
     * @throws InvalidArgumentException
2545
     * @throws InvalidDataTypeException
2546
     * @throws InvalidInterfaceException
2547
     * @throws ReflectionException
2548
     * @throws RuntimeException
2549
     */
2550
    public function recalculateLineItems()
2551
    {
2552
        $TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2553
        /** @var EE_Transaction $transaction */
2554
        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2555
        $total_line_item = $transaction->total_line_item(false);
2556
        $success = false;
2557
        if ($total_line_item instanceof EE_Line_Item) {
2558
            EEH_Line_Item::resetIsTaxableForTickets($total_line_item);
2559
            $success = EEH_Line_Item::apply_taxes($total_line_item, true);
2560
        }
2561
        $this->_redirect_after_action(
2562
            (bool) $success,
2563
            esc_html__('Transaction taxes and totals', 'event_espresso'),
2564
            esc_html__('recalculated', 'event_espresso'),
2565
            isset($this->_req_data['redirect_to'])
2566
                ? array(
2567
                'action' => $this->_req_data['redirect_to'],
2568
                'TXN_ID' => $this->_req_data['TXN_ID'],
2569
            )
2570
                : array(),
2571
            true
2572
        );
2573
    }
2574
}
2575