Completed
Branch FET-9586-add-search-input (524ff8)
by
unknown
1332:39 queued 1318:06
created

Transactions_Admin_Page   F

Complexity

Total Complexity 197

Size/Duplication

Total Lines 1804
Duplicated Lines 3.44 %

Coupling/Cohesion

Components 2
Dependencies 39

Importance

Changes 0
Metric Value
dl 62
loc 1804
rs 0.5217
c 0
b 0
f 0
wmc 197
lcom 2
cbo 39

50 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A _init_page_props() 6 6 1
A _ajax_hooks() 0 5 1
A _define_page_props() 10 10 1
B _set_page_routes() 0 46 3
A _set_page_config() 0 63 2
A _add_screen_options() 0 1 1
A _add_feature_pointers() 0 1 1
A admin_init() 0 20 2
A admin_notices() 0 1 1
A admin_footer_scripts() 0 1 1
A _set_transaction_status_array() 0 3 1
A get_transaction_status_array() 0 3 1
A _get_payment_status_array() 0 5 1
A _add_screen_options_default() 0 3 1
A load_scripts_styles() 0 13 1
A load_scripts_styles_view_transaction() 0 4 1
A load_scripts_styles_default() 0 4 1
A _set_list_table_views_default() 0 19 1
B _set_transaction_object() 0 17 5
B _transaction_legend_items() 9 83 6
A _transactions_overview_list_table() 0 7 3
F _transaction_details() 8 171 21
A _transaction_details_metaboxes() 0 18 1
F txn_details_meta_box() 0 83 11
C _get_registration_payment_IDs() 0 27 8
C _get_registrations_to_apply_payment_to() 0 52 8
A _get_reg_status_selection() 0 10 1
A _get_payment_methods() 0 16 4
C txn_attendees_meta_box() 0 60 10
A txn_registrant_side_meta_box() 0 16 3
A txn_billing_info_side_meta_box() 0 11 1
B apply_payments_or_refunds() 0 44 4
C _validate_payment_request_data() 7 29 7
B _generate_payment_form_section() 0 93 1
B _create_payment_from_request_data() 0 38 5
A _process_transaction_payments() 0 13 2
A _get_REG_IDs_to_apply_payment_to() 0 14 4
A existing_reg_payment_REG_IDs() 0 3 1
A set_existing_reg_payment_REG_IDs() 0 3 1
A _get_existing_reg_payment_REG_IDs() 0 10 3
A _remove_existing_registration_payments() 0 21 3
A _update_registration_payments() 0 21 3
A _process_registration_status_change() 0 18 3
B _build_payment_json_response() 0 34 4
C delete_payment() 0 42 7
A _registration_payment_data_array() 0 16 4
C _maybe_send_notifications() 22 28 7
A _send_payment_reminder() 0 7 3
F get_transactions() 0 108 30

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Transactions_Admin_Page often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Transactions_Admin_Page, and based on these observations, apply Extract Interface, too.

1
<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) exit('No direct script access allowed');
2
/**
3
 * Event Espresso
4
 *
5
 * Event Registration and Management Plugin for WordPress
6
 *
7
 * @ package			Event Espresso
8
 * @ author				Seth Shoultes
9
 * @ copyright		(c) 2008-2011 Event Espresso  All Rights Reserved.
10
 * @ license			{@link http://eventespresso.com/support/terms-conditions/}   * see Plugin Licensing *
11
 * @ link					{@link http://www.eventespresso.com}
12
 * @ since		 		4.0
13
 *
14
 * ------------------------------------------------------------------------
15
 *
16
 * EE_Admin_Transactions class
17
 *
18
 * @package			Event Espresso
19
 * @subpackage	includes/core/admin/transactions/Transactions_Admin_Page.core.php
20
 * @author				Brent Christensen
21
 *
22
 * ------------------------------------------------------------------------
23
 */
24
class Transactions_Admin_Page extends EE_Admin_Page {
25
26
	/**
27
	 * @var EE_Transaction
28
	 */
29
	private $_transaction;
30
31
	/**
32
	 * @var EE_Session
33
	 */
34
	private $_session;
35
36
	/**
37
	 * @var array $_txn_status
38
	 */
39
	private static $_txn_status;
40
41
	/**
42
	 * @var array $_pay_status
43
	 */
44
	private static $_pay_status;
45
46
	/**
47
	 * @var array $_existing_reg_payment_REG_IDs
48
	 */
49
	protected $_existing_reg_payment_REG_IDs = null;
50
51
52
53
	/**
54
	 * @Constructor
55
	 * @access public
56
	 * @param bool $routing
57
	 * @return Transactions_Admin_Page
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
58
	 */
59
	public function __construct( $routing = TRUE ) {
60
		parent::__construct( $routing );
61
	}
62
63
64
65
	/**
66
	 * 	_init_page_props
67
	 * @return void
68
	 */
69 View Code Duplication
	protected function _init_page_props() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
70
		$this->page_slug = TXN_PG_SLUG;
71
		$this->page_label = __('Transactions', 'event_espresso');
72
		$this->_admin_base_url = TXN_ADMIN_URL;
73
		$this->_admin_base_path = TXN_ADMIN;
74
	}
75
76
77
78
	/**
79
	 * 	_ajax_hooks
80
	 * @return void
81
	 */
82
	protected function _ajax_hooks() {
83
		add_action('wp_ajax_espresso_apply_payment', array( $this, 'apply_payments_or_refunds'));
84
		add_action('wp_ajax_espresso_apply_refund', array( $this, 'apply_payments_or_refunds'));
85
		add_action('wp_ajax_espresso_delete_payment', array( $this, 'delete_payment'));
86
	}
87
88
89
90
	/**
91
	 * 	_define_page_props
92
	 * @return void
93
	 */
94 View Code Duplication
	protected function  _define_page_props() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
95
		$this->_admin_page_title = $this->page_label;
96
		$this->_labels = array(
97
			'buttons' => array(
98
				'add' => __('Add New Transaction', 'event_espresso'),
99
				'edit' => __('Edit Transaction', 'event_espresso'),
100
				'delete' => __('Delete Transaction','event_espresso'),
101
			)
102
		);
103
	}
104
105
106
107
	/**
108
	 * 		grab url requests and route them
109
	*		@access private
110
	*		@return void
111
	*/
112
	public function _set_page_routes() {
113
114
		$this->_set_transaction_status_array();
115
116
		$txn_id = ! empty( $this->_req_data['TXN_ID'] ) && ! is_array( $this->_req_data['TXN_ID'] ) ? $this->_req_data['TXN_ID'] : 0;
117
118
		$this->_page_routes = array(
119
120
				'default' => array(
121
					'func' => '_transactions_overview_list_table',
122
					'capability' => 'ee_read_transactions'
123
					),
124
125
				'view_transaction' => array(
126
					'func' => '_transaction_details',
127
					'capability' => 'ee_read_transaction',
128
					'obj_id' => $txn_id
129
					),
130
131
				'send_payment_reminder'	=> array(
132
					'func' => '_send_payment_reminder',
133
					'noheader' => TRUE,
134
					'capability' => 'ee_send_message'
135
					),
136
137
				'espresso_apply_payment' => array(
138
				 	'func' => 'apply_payments_or_refunds',
139
				 	'noheader' => TRUE,
140
				 	'capability' => 'ee_edit_payments'
141
				 	),
142
143
				'espresso_apply_refund'	=> array(
144
					'func' => 'apply_payments_or_refunds',
145
					'noheader' => TRUE,
146
					'capability' => 'ee_edit_payments'
147
					),
148
149
				'espresso_delete_payment' => array(
150
					'func' => 'delete_payment',
151
					'noheader' => TRUE,
152
					'capability' => 'ee_delete_payments'
153
					),
154
155
		);
156
157
	}
158
159
160
161
162
163
164
165
166
	protected function _set_page_config() {
167
		$this->_page_config = array(
168
			'default' => array(
169
				'nav' => array(
170
					'label' => __('Overview', 'event_espresso'),
171
					'order' => 10
172
					),
173
				'list_table' => 'EE_Admin_Transactions_List_Table',
174
				'help_tabs' => array(
175
					'transactions_overview_help_tab' => array(
176
						'title' => __('Transactions Overview', 'event_espresso'),
177
						'filename' => 'transactions_overview'
178
					),
179
					'transactions_overview_table_column_headings_help_tab' => array(
180
						'title' => __('Transactions Table Column Headings', 'event_espresso'),
181
						'filename' => 'transactions_overview_table_column_headings'
182
					),
183
					'transactions_overview_views_filters_help_tab' => array(
184
						'title' => __('Transaction Views & Filters & Search', 'event_espresso'),
185
						'filename' => 'transactions_overview_views_filters_search'
186
					),
187
				),
188
				'help_tour' => array( 'Transactions_Overview_Help_Tour' ),
189
				/**
190
				 * commented out because currently we are not displaying tips for transaction list table status but this
191
				 * may change in a later iteration so want to keep the code for then.
192
				 */
193
				//'qtips' => array( 'Transactions_List_Table_Tips' ),
194
				'require_nonce' => FALSE
195
				),
196
			'view_transaction' => array(
197
				'nav' => array(
198
					'label' => __('View Transaction', 'event_espresso'),
199
					'order' => 5,
200
					'url' => isset($this->_req_data['TXN_ID']) ? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID'] ), $this->_current_page_view_url )  : $this->_admin_base_url,
201
					'persistent' => FALSE
202
					),
203
				'help_tabs' => array(
204
					'transactions_view_transaction_help_tab' => array(
205
						'title' => __('View Transaction', 'event_espresso'),
206
						'filename' => 'transactions_view_transaction'
207
					),
208
					'transactions_view_transaction_transaction_details_table_help_tab' => array(
209
						'title' => __('Transaction Details Table', 'event_espresso'),
210
						'filename' => 'transactions_view_transaction_transaction_details_table'
211
					),
212
					'transactions_view_transaction_attendees_registered_help_tab' => array(
213
						'title' => __('Attendees Registered', 'event_espresso'),
214
						'filename' => 'transactions_view_transaction_attendees_registered'
215
					),
216
					'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
217
						'title' => __('Primary Registrant & Billing Information', 'event_espresso'),
218
						'filename' => 'transactions_view_transaction_primary_registrant_billing_information'
219
					),
220
				),
221
				'qtips' => array( 'Transaction_Details_Tips' ),
222
				'help_tour' => array( 'Transaction_Details_Help_Tour' ),
223
				'metaboxes' => array('_transaction_details_metaboxes'),
224
225
				'require_nonce' => FALSE
226
				)
227
		);
228
	}
229
230
231
	/**
232
	 * The below methods aren't used by this class currently
233
	 */
234
	protected function _add_screen_options() {}
235
	protected function _add_feature_pointers() {}
236
	public function admin_init() {
237
		// IF a registration was JUST added via the admin...
238
		if (
239
		isset(
240
			$this->_req_data[ 'redirect_from' ],
241
			$this->_req_data[ 'EVT_ID' ],
242
			$this->_req_data[ 'event_name' ]
243
		)
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( 'ee_registration_added', $this->_req_data[ 'EVT_ID' ], time() + WEEK_IN_SECONDS, '/' );
248
			// and update the global
249
			$_COOKIE[ 'ee_registration_added' ] = $this->_req_data[ 'EVT_ID' ];
250
		}
251
		EE_Registry::$i18n_js_strings[ 'invalid_server_response' ] = __( '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.', 'event_espresso' );
252
		EE_Registry::$i18n_js_strings[ 'error_occurred' ] = __( 'An error occurred! Please refresh the page and try again.', 'event_espresso' );
253
		EE_Registry::$i18n_js_strings[ 'txn_status_array' ] = self::$_txn_status;
254
		EE_Registry::$i18n_js_strings[ 'pay_status_array' ] = self::$_pay_status;
255
	}
256
	public function admin_notices() {}
257
	public function admin_footer_scripts() {}
258
259
260
261
	/**
262
	 * _set_transaction_status_array
263
	 * sets list of transaction statuses
264
	*
265
	 * @access private
266
	*	@return void
267
	*/
268
	private function _set_transaction_status_array() {
269
		self::$_txn_status = EEM_Transaction::instance()->status_array(TRUE);
270
	}
271
272
273
274
	/**
275
	 * get_transaction_status_array
276
	 * return the transaction status array for wp_list_table
277
	 *
278
	 * @access public
279
	 * @return array
280
	 */
281
	public function get_transaction_status_array() {
282
		return self::$_txn_status;
283
	}
284
285
286
287
	/**
288
	 * 	get list of payment statuses
289
	*
290
	 * @access private
291
	*	@return void
292
	*/
293
	private function _get_payment_status_array() {
294
		self::$_pay_status = EEM_Payment::instance()->status_array(TRUE);
295
		$this->_template_args['payment_status'] = self::$_pay_status;
296
297
	}
298
299
300
301
	/**
302
	 * 	_add_screen_options_default
303
	 *
304
	 * 	@access protected
305
	 *	@return void
306
	 */
307
	protected function _add_screen_options_default() {
308
		$this->_per_page_screen_option();
309
	}
310
311
312
313
	/**
314
	 * load_scripts_styles
315
	 *
316
	 * @access public
317
	 *	@return void
318
	 */
319
	public function load_scripts_styles() {
320
		//enqueue style
321
		wp_register_style( 'espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.css', array(), EVENT_ESPRESSO_VERSION );
322
		wp_enqueue_style('espresso_txn');
323
324
		//scripts
325
		add_filter('FHEE_load_accounting_js', '__return_true');
326
327
		//scripts
328
		wp_register_script('espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.js', array('ee_admin_js', 'ee-datepicker', 'jquery-ui-datepicker', 'jquery-ui-draggable', 'ee-dialog', 'ee-accounting', 'ee-serialize-full-array'), EVENT_ESPRESSO_VERSION, TRUE);
329
		wp_enqueue_script('espresso_txn');
330
331
	}
332
333
334
335
	/**
336
	 * 	load_scripts_styles_view_transaction
337
	 *
338
	 *	@access public
339
	 *	@return void
340
	 */
341
	public function load_scripts_styles_view_transaction() {
342
		//styles
343
		wp_enqueue_style('espresso-ui-theme');
344
	}
345
346
347
348
	/**
349
	 * 	load_scripts_styles_default
350
	 *
351
	 * @access public
352
	 *	@return void
353
	 */
354
	public function load_scripts_styles_default() {
355
		//styles
356
		wp_enqueue_style('espresso-ui-theme');
357
	}
358
359
360
361
	/**
362
	 * 	_set_list_table_views_default
363
	 *
364
	 *	@access protected
365
	 *	@return void
366
	 */
367
	protected function _set_list_table_views_default() {
368
		$this->_views = array (
369
			'all' => array (
370
				'slug' 		=> 'all',
371
				'label' 		=> __('View All Transactions', 'event_espresso'),
372
				'count' 	=> 0
373
				),
374
			'abandoned' => array(
375
				'slug' 		=> 'abandoned',
376
				'label' 		=> __('Abandoned Transactions', 'event_espresso'),
377
				'count' 	=> 0
378
			),
379
			'failed' => array(
380
				'slug' 		=> 'failed',
381
				'label' 		=> __('Failed Transactions', 'event_espresso'),
382
				'count' 	=> 0
383
			)
384
		);
385
	}
386
387
388
389
	/**
390
	 * _set_transaction_object
391
	 * This sets the _transaction property for the transaction details screen
392
	 *
393
	 *	@access private
394
	 *	@return void
395
	 */
396
	private function _set_transaction_object() {
397
		if ( is_object( $this->_transaction) )
398
			return; //get out we've already set the object
399
400
	    $TXN = EEM_Transaction::instance();
401
402
	    $TXN_ID = ( ! empty( $this->_req_data['TXN_ID'] )) ? absint( $this->_req_data['TXN_ID'] ) : FALSE;
403
404
	    //get transaction object
405
	    $this->_transaction = $TXN->get_one_by_ID($TXN_ID);
0 ignored issues
show
Documentation Bug introduced by
It seems like $TXN->get_one_by_ID($TXN_ID) can also be of type object<EE_Base_Class>. However, the property $_transaction is declared as type object<EE_Transaction>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
406
	    $this->_session = !empty( $this->_transaction ) ? $this->_transaction->get('TXN_session_data') : NULL;
407
408
	 	if ( empty( $this->_transaction ) ) {
409
	    	$error_msg = __('An error occurred and the details for Transaction ID #', 'event_espresso') . $TXN_ID .  __(' could not be retrieved.', 'event_espresso');
410
			EE_Error::add_error( $error_msg, __FILE__, __FUNCTION__, __LINE__ );
411
	    }
412
	}
413
414
415
416
	/**
417
	 * 	_transaction_legend_items
418
	 *
419
	 *	@access protected
420
	 *	@return array
421
	 */
422
	protected function _transaction_legend_items() {
423
		EE_Registry::instance()->load_helper( 'MSG_Template' );
424
425 View Code Duplication
		if ( EE_Registry::instance()->CAP->current_user_can( 'ee_read_messages', 'view_filtered_messages' ) ) {
426
			$related_for_icon = EEH_MSG_Template::get_message_action_icon( 'see_notifications_for' );
427
			if ( isset( $related_for_icon['css_class']) && isset( $related_for_icon['label'] ) ) {
428
				$items['view_related_messages'] = array(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$items was never initialized. Although not strictly required by PHP, it is generally a good practice to add $items = 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...
429
					'class' => $related_for_icon['css_class'],
430
					'desc' => $related_for_icon['label'],
431
				);
432
			}
433
		}
434
435
		$items = apply_filters(
436
			'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
437
			array_merge( $items,
0 ignored issues
show
Bug introduced by
The variable $items does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
438
				array(
439
					'view_details' => array(
440
						'class' => 'dashicons dashicons-cart',
441
						'desc' => __('View Transaction Details', 'event_espresso')
442
					),
443
					'view_invoice' => array(
444
						'class' => 'dashicons dashicons-media-spreadsheet',
445
						'desc' => __('View Transaction Invoice', 'event_espresso')
446
					),
447
					'view_receipt' => array(
448
						'class' => 'dashicons dashicons-media-default',
449
						'desc' => __('View Transaction Receipt', 'event_espresso' )
450
					),
451
					'view_registration' => array(
452
						'class' => 'dashicons dashicons-clipboard',
453
						'desc' => __('View Registration Details', 'event_espresso')
454
					)
455
				)
456
			)
457
		);
458
459
		if ( EE_Registry::instance()->CAP->current_user_can( 'ee_send_message', 'espresso_transactions_send_payment_reminder' ) ) {
460
			if ( EEH_MSG_Template::is_mt_active( 'payment_reminder' ) ) {
461
				$items['send_payment_reminder'] = array(
462
					'class' => 'dashicons dashicons-email-alt',
463
					'desc' => __('Send Payment Reminder', 'event_espresso')
464
					);
465
			} else {
466
				$items['blank*'] = array(
467
					'class'=> '',
468
					'desc' => ''
469
					);
470
			}
471
		} else {
472
			$items['blank*'] = array(
473
				'class'=> '',
474
				'desc' => ''
475
				);
476
		}
477
		$more_items = apply_filters(
478
			'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
479
			array(
480
				'overpaid'   => array(
481
					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
482
					'desc'  => EEH_Template::pretty_status( EEM_Transaction::overpaid_status_code, FALSE, 'sentence' )
483
				),
484
				'complete'   => array(
485
					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
486
					'desc'  => EEH_Template::pretty_status( EEM_Transaction::complete_status_code, FALSE, 'sentence' )
487
				),
488
				'incomplete' => array(
489
					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
490
					'desc'  => EEH_Template::pretty_status( EEM_Transaction::incomplete_status_code, FALSE, 'sentence' )
491
				),
492
				'abandoned'  => array(
493
					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
494
					'desc'  => EEH_Template::pretty_status( EEM_Transaction::abandoned_status_code, FALSE, 'sentence' )
495
				),
496
				'failed'     => array(
497
					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
498
					'desc'  => EEH_Template::pretty_status( EEM_Transaction::failed_status_code, FALSE, 'sentence' )
499
				)
500
			)
501
		);
502
503
		return array_merge( $items, $more_items);
504
	}
505
506
507
508
	/**
509
	 * 	_transactions_overview_list_table
510
	 *
511
	 * @access protected
512
	 *	@return void
513
	 */
514
	protected function _transactions_overview_list_table() {
515
		$this->_admin_page_title = __('Transactions', 'event_espresso');
516
		$event = isset($this->_req_data['EVT_ID']) ? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID'] ) : NULL;
517
		$this->_template_args['admin_page_header'] = $event instanceof EE_Event ? sprintf( __('%sViewing Transactions for the Event: %s%s', 'event_espresso'), '<h3>', '<a href="' . EE_Admin_Page::add_query_args_and_nonce(array('action' => 'edit', 'post' => $event->ID()), EVENTS_ADMIN_URL ) . '" title="' . esc_attr__('Click to Edit event', 'event_espresso') . '">' . $event->get('EVT_name') . '</a>', '</h3>' ) : '';
518
		$this->_template_args['after_list_table'] = $this->_display_legend( $this->_transaction_legend_items() );
519
		$this->display_admin_list_table_page_with_no_sidebar();
520
	}
521
522
523
524
	/**
525
	* 	_transaction_details
526
	 * generates HTML for the View Transaction Details Admin page
527
	*
528
	 * @access protected
529
	*	@return void
530
	*/
531
	protected function _transaction_details() {
532
		do_action( 'AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction );
533
534
		$this->_set_transaction_status_array();
535
536
		$this->_template_args = array();
537
		$this->_template_args['transactions_page'] = $this->_wp_page_slug;
538
539
		$this->_set_transaction_object();
540
541
		$primary_registration = $this->_transaction->primary_registration();
542
		$attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee() : NULL;
543
544
		$this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
545
		$this->_template_args['txn_nmbr']['label'] = __( 'Transaction Number', 'event_espresso' );
546
547
		$this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
548
		$this->_template_args['txn_datetime']['label'] = __( 'Date', 'event_espresso' );
549
550
		$this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->get('STS_ID') ];
551
		$this->_template_args['txn_status']['label'] = __( 'Transaction Status', 'event_espresso' );
552
		$this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->get('STS_ID');
553
554
		$this->_template_args['grand_total'] = $this->_transaction->get('TXN_total');
555
		$this->_template_args['total_paid'] = $this->_transaction->get('TXN_paid');
556
557
		if (
558
			$attendee instanceof EE_Attendee
559
			&& EE_Registry::instance()->CAP->current_user_can(
560
				'ee_send_message',
561
				'espresso_transactions_send_payment_reminder'
562
			)
563
		) {
564
			$this->_template_args['send_payment_reminder_button'] =
565
				EEH_MSG_Template::is_mt_active( 'payment_reminder' )
566
				&& $this->_transaction->get('STS_ID') != EEM_Transaction::complete_status_code
567
				&& $this->_transaction->get('STS_ID') != EEM_Transaction::overpaid_status_code
568
					? EEH_Template::get_button_or_link(
569
						EE_Admin_Page::add_query_args_and_nonce(
570
							array(
571
								'action'=>'send_payment_reminder',
572
								'TXN_ID'=>$this->_transaction->ID(),
573
								'redirect_to' => 'view_transaction'
574
							),
575
							TXN_ADMIN_URL
576
						),
577
						__(' Send Payment Reminder', 'event_espresso'),
578
						'button secondary-button right',
579
						'dashicons dashicons-email-alt'
580
					)
581
				    : '';
582
		} else {
583
			$this->_template_args['send_payment_reminder_button'] = '';
584
		}
585
586
		$amount_due = $this->_transaction->get('TXN_total') - $this->_transaction->get('TXN_paid');
587
		$this->_template_args['amount_due'] = EEH_Template::format_currency( $amount_due, TRUE );
588
		if ( EE_Registry::instance()->CFG->currency->sign_b4 ) {
589
			$this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign . $this->_template_args['amount_due'];
590
		} else {
591
			$this->_template_args['amount_due'] = $this->_template_args['amount_due'] . EE_Registry::instance()->CFG->currency->sign;
592
		}
593
		$this->_template_args['amount_due_class'] =  '';
594
595
		if ( $this->_transaction->get('TXN_paid') == $this->_transaction->get('TXN_total') ) {
596
			// paid in full
597
			$this->_template_args['amount_due'] =  FALSE;
598 View Code Duplication
		} elseif ( $this->_transaction->get('TXN_paid') > $this->_transaction->get('TXN_total') ) {
599
			// overpaid
600
			$this->_template_args['amount_due_class'] =  'txn-overview-no-payment-spn';
601
		} elseif (( $this->_transaction->get('TXN_total') > 0 ) && ( $this->_transaction->get('TXN_paid') > 0 )) {
602
			// monies owing
603
			$this->_template_args['amount_due_class'] =  'txn-overview-part-payment-spn';
604 View Code Duplication
		} elseif (( $this->_transaction->get('TXN_total') > 0 ) && ( $this->_transaction->get('TXN_paid') == 0 )) {
605
			// no payments made yet
606
			$this->_template_args['amount_due_class'] =  'txn-overview-no-payment-spn';
607
		} elseif ( $this->_transaction->get('TXN_total') == 0 ) {
608
			// free event
609
			$this->_template_args['amount_due'] =  FALSE;
610
		}
611
612
		$payment_method = $this->_transaction->payment_method();
613
614
		$this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
615
			? $payment_method->admin_name()
616
			: __( 'Unknown', 'event_espresso' );
617
618
		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
619
		// link back to overview
620
		$this->_template_args['txn_overview_url'] = ! empty ( $_SERVER['HTTP_REFERER'] )
621
			? $_SERVER['HTTP_REFERER']
622
			: TXN_ADMIN_URL;
623
624
625
		// next link
626
		$next_txn = $this->_transaction->next(
627
			null,
628
			array( array( 'STS_ID' => array( '!=', EEM_Transaction::failed_status_code ) ) ),
629
			'TXN_ID'
630
		);
631
		$this->_template_args['next_transaction'] = $next_txn
632
			? $this->_next_link(
633
				EE_Admin_Page::add_query_args_and_nonce(
634
					array( 'action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID'] ),
635
					TXN_ADMIN_URL
636
				),
637
				'dashicons dashicons-arrow-right ee-icon-size-22'
638
			)
639
			: '';
640
		// previous link
641
		$previous_txn = $this->_transaction->previous(
642
			null,
643
			array( array( 'STS_ID' => array( '!=', EEM_Transaction::failed_status_code ) ) ),
644
			'TXN_ID'
645
		);
646
		$this->_template_args['previous_transaction'] = $previous_txn
647
			? $this->_previous_link(
648
				EE_Admin_Page::add_query_args_and_nonce(
649
					array( 'action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID'] ),
650
					TXN_ADMIN_URL
651
				),
652
				'dashicons dashicons-arrow-left ee-icon-size-22'
653
			)
654
			: '';
655
656
		// were we just redirected here after adding a new registration ???
657
		if (
658
			isset(
659
				$this->_req_data[ 'redirect_from' ],
660
				$this->_req_data[ 'EVT_ID' ],
661
				$this->_req_data[ 'event_name' ]
662
			)
663
		) {
664
			if (
665
				EE_Registry::instance()->CAP->current_user_can(
666
					'ee_edit_registrations',
667
					'espresso_registrations_new_registration',
668
					$this->_req_data[ 'EVT_ID' ]
669
				)
670
			) {
671
				$this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
672
				$this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
673
					array(
674
						'page'     => 'espresso_registrations',
675
						'action'   => 'new_registration',
676
						'return'   => 'default',
677
						'TXN_ID'   => $this->_transaction->ID(),
678
						'event_id' => $this->_req_data[ 'EVT_ID' ],
679
					),
680
					REG_ADMIN_URL
681
				);
682
				$this->_admin_page_title .= '">';
683
684
				$this->_admin_page_title .= sprintf(
685
					__('Add Another New Registration to Event: "%1$s" ?'),
686
					htmlentities( urldecode( $this->_req_data[ 'event_name' ] ), ENT_QUOTES, 'UTF-8' )
687
				);
688
				$this->_admin_page_title .= '</a>';
689
			}
690
			EE_Registry::instance()->SSN->clear_session( __CLASS__, __FUNCTION__ );
691
		}
692
		// grab messages at the last second
693
		$this->_template_args['notices'] = EE_Error::get_notices();
694
		// path to template
695
		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
696
		$this->_template_args['admin_page_header'] = EEH_Template::display_template( $template_path, $this->_template_args, TRUE );
697
698
		// the details template wrapper
699
		$this->display_admin_page_with_sidebar();
700
701
	}
702
703
704
705
	/**
706
	 * 		_transaction_details_metaboxes
707
	 *
708
	 *		@access protected
709
	 *		@return void
710
	 */
711
	protected function _transaction_details_metaboxes() {
712
713
		$this->_set_transaction_object();
714
715
		add_meta_box( 'edit-txn-details-mbox', __( 'Transaction Details', 'event_espresso' ), array( $this, 'txn_details_meta_box' ), $this->_wp_page_slug, 'normal', 'high' );
716
		add_meta_box(
717
			'edit-txn-attendees-mbox',
718
			__( 'Attendees Registered in this Transaction', 'event_espresso' ),
719
			array( $this, 'txn_attendees_meta_box' ),
720
			$this->_wp_page_slug,
721
			'normal',
722
			'high',
723
			array( 'TXN_ID' => $this->_transaction->ID() )
724
		);
725
		add_meta_box( 'edit-txn-registrant-mbox', __( 'Primary Contact', 'event_espresso' ), array( $this, 'txn_registrant_side_meta_box' ), $this->_wp_page_slug, 'side', 'high' );
726
		add_meta_box( 'edit-txn-billing-info-mbox', __( 'Billing Information', 'event_espresso' ), array( $this, 'txn_billing_info_side_meta_box' ), $this->_wp_page_slug, 'side', 'high' );
727
728
	}
729
730
731
732
	/**
733
	 * txn_details_meta_box
734
	 * generates HTML for the Transaction main meta box
735
	*
736
	 * @access public
737
	*	@return void
738
	*/
739
	public function txn_details_meta_box() {
740
741
		$this->_set_transaction_object();
742
		$this->_template_args['TXN_ID'] = $this->_transaction->ID();
743
		$this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration ? $this->_transaction->primary_registration()->attendee() : null;
744
745
		//get line table
746
		EEH_Autoloader::register_line_item_display_autoloaders();
747
		$Line_Item_Display = new EE_Line_Item_Display( 'admin_table', 'EE_Admin_Table_Line_Item_Display_Strategy' );
748
		$this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item( $this->_transaction->total_line_item() );
749
		$this->_template_args['REG_code'] = $this->_transaction->get_first_related('Registration')->get('REG_code');
750
751
		// process taxes
752
		$taxes = $this->_transaction->get_many_related( 'Line_Item', array( array( 'LIN_type' => EEM_Line_Item::type_tax )));
753
		$this->_template_args['taxes'] = ! empty( $taxes ) ? $taxes : FALSE;
754
755
		$this->_template_args['grand_total'] = EEH_Template::format_currency($this->_transaction->get('TXN_total'), FALSE, FALSE );
756
		$this->_template_args['grand_raw_total'] = $this->_transaction->get('TXN_total');
757
		$this->_template_args['TXN_status'] = $this->_transaction->get('STS_ID');
758
759
//		$txn_status_class = 'status-' . $this->_transaction->get('STS_ID');
760
761
		// process payment details
762
		$payments = $this->_transaction->get_many_related('Payment');
763
		if( ! empty(  $payments ) ) {
764
			$this->_template_args[ 'payments' ] = $payments;
765
			$this->_template_args[ 'existing_reg_payments' ] = $this->_get_registration_payment_IDs( $payments );
0 ignored issues
show
Documentation introduced by
$payments is of type array<integer,object<EE_Base_Class>>, but the function expects a array<integer,object<EE_Payment>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
766
		} else {
767
			$this->_template_args[ 'payments' ] = false;
768
			$this->_template_args[ 'existing_reg_payments' ] = array();
769
		}
770
771
		$this->_template_args['edit_payment_url'] = add_query_arg( array( 'action' => 'edit_payment'  ), TXN_ADMIN_URL );
772
		$this->_template_args['delete_payment_url'] = add_query_arg( array( 'action' => 'espresso_delete_payment' ), TXN_ADMIN_URL );
773
774
		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...
775
			$this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
776
			$this->_template_args['txn_details']['invoice_number']['label'] = __( 'Invoice Number', 'event_espresso' );
777
		}
778
779
		$this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction->get_first_related('Registration')->get('REG_session');
780
		$this->_template_args['txn_details']['registration_session']['label'] = __( 'Registration Session', 'event_espresso' );
781
782
		$this->_template_args['txn_details']['ip_address']['value'] = isset( $this->_session['ip_address'] ) ? $this->_session['ip_address'] : '';
783
		$this->_template_args['txn_details']['ip_address']['label'] = __( 'Transaction placed from IP', 'event_espresso' );
784
785
		$this->_template_args['txn_details']['user_agent']['value'] = isset( $this->_session['user_agent'] ) ? $this->_session['user_agent'] : '';
786
		$this->_template_args['txn_details']['user_agent']['label'] = __( 'Registrant User Agent', 'event_espresso' );
787
788
		$reg_steps = '<ul>';
789
		foreach ( $this->_transaction->reg_steps() as $reg_step => $reg_step_status ) {
790
			if ( $reg_step_status === true ) {
791
				$reg_steps .= '<li style="color:#70cc50">' . sprintf( __( '%1$s : Completed', 'event_espresso' ), ucwords( str_replace( '_', ' ', $reg_step ) ) ) . '</li>';
792
			} else if ( is_numeric( $reg_step_status ) && $reg_step_status !== false ) {
793
					$reg_steps .= '<li style="color:#2EA2CC">' . sprintf(
794
							__( '%1$s : Initiated %2$s', 'event_espresso' ),
795
							ucwords( str_replace( '_', ' ', $reg_step ) ),
796
							gmdate( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), ( $reg_step_status + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) ) )
797
						) . '</li>';
798
				} else {
799
				$reg_steps .= '<li style="color:#E76700">' . sprintf( __( '%1$s : Never Initiated', 'event_espresso' ), ucwords( str_replace( '_', ' ', $reg_step ) ) ) . '</li>';
800
			}
801
		}
802
		$reg_steps .= '</ul>';
803
		$this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
804
		$this->_template_args['txn_details']['reg_steps']['label'] = __( 'Registration Step Progress', 'event_espresso' );
805
806
807
		$this->_get_registrations_to_apply_payment_to();
808
		$this->_get_payment_methods( $payments );
809
		$this->_get_payment_status_array();
810
		$this->_get_reg_status_selection(); //sets up the template args for the reg status array for the transaction.
811
812
		$this->_template_args['transaction_form_url'] = add_query_arg( array( 'action' => 'edit_transaction', 'process' => 'transaction'  ), TXN_ADMIN_URL );
813
		$this->_template_args['apply_payment_form_url'] = add_query_arg( array( 'page' => 'espresso_transactions', 'action' => 'espresso_apply_payment' ), WP_AJAX_URL );
814
		$this->_template_args['delete_payment_form_url'] = add_query_arg( array( 'page' => 'espresso_transactions', 'action' => 'espresso_delete_payment' ), WP_AJAX_URL );
815
816
		// 'espresso_delete_payment_nonce'
817
818
		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
819
		echo EEH_Template::display_template( $template_path, $this->_template_args, TRUE );
820
821
	}
822
823
824
825
	/**
826
	 * _get_registration_payment_IDs
827
	 *
828
	 *    generates an array of Payment IDs and their corresponding Registration IDs
829
	 *
830
	 * @access protected
831
	 * @param EE_Payment[] $payments
832
	 * @return array
833
	 */
834
	protected function _get_registration_payment_IDs( $payments = array() ) {
835
		$existing_reg_payments = array();
836
		// get all reg payments for these payments
837
		$reg_payments = EEM_Registration_Payment::instance()->get_all( array(
838
			array(
839
				'PAY_ID' => array(
840
					'IN',
841
					array_keys( $payments )
842
				)
843
			)
844
		) );
845
		if ( ! empty( $reg_payments ) ) {
846
			foreach ( $payments as $payment ) {
847
				if ( ! $payment instanceof EE_Payment ) {
848
					continue;
849
				} else if ( ! isset( $existing_reg_payments[ $payment->ID() ] ) ) {
850
					$existing_reg_payments[ $payment->ID() ] = array();
851
				}
852
				foreach ( $reg_payments as $reg_payment ) {
853
					if ( $reg_payment instanceof EE_Registration_Payment && $reg_payment->payment_ID() === $payment->ID() ) {
854
						$existing_reg_payments[ $payment->ID() ][ ] = $reg_payment->registration_ID();
855
					}
856
				}
857
			}
858
		}
859
		return $existing_reg_payments;
860
	}
861
862
863
864
	/**
865
	 * _get_registrations_to_apply_payment_to
866
	 *
867
	 * 	generates HTML for displaying a series of checkboxes in the admin payment modal window
868
	 * which allows the admin to only apply the payment to the specific registrations
869
	 *
870
	 *	@access protected
871
	 * @return void
872
	 */
873
	protected function _get_registrations_to_apply_payment_to() {
874
		// we want any registration with an active status (ie: not deleted or cancelled)
875
		$query_params = array(
876
			array(
877
				'STS_ID' => array(
878
					'IN',
879
					array(
880
						EEM_Registration::status_id_approved,
881
						EEM_Registration::status_id_pending_payment,
882
						EEM_Registration::status_id_not_approved,
883
					)
884
				)
885
			)
886
		);
887
		$registrations_to_apply_payment_to = '<br /><div id="txn-admin-apply-payment-to-registrations-dv"  style="clear: both; margin: 1.5em 0 0; display: none;">';
888
		$registrations_to_apply_payment_to .= '<br /><div class="admin-primary-mbox-tbl-wrap">';
889
		$registrations_to_apply_payment_to .= '<table class="admin-primary-mbox-tbl">';
890
		$registrations_to_apply_payment_to .= '<thead><tr>';
891
		$registrations_to_apply_payment_to .= '<td>' . __( 'ID', 'event_espresso' ) . '</td>';
892
		$registrations_to_apply_payment_to .= '<td>' . __( 'Registrant', 'event_espresso' ) . '</td>';
893
		$registrations_to_apply_payment_to .= '<td>' . __( 'Ticket', 'event_espresso' ) . '</td>';
894
		$registrations_to_apply_payment_to .= '<td>' . __( 'Event', 'event_espresso' ) . '</td>';
895
		$registrations_to_apply_payment_to .= '<td class="txn-admin-payment-paid-td jst-cntr">' . __( 'Paid', 'event_espresso' ) . '</td>';
896
		$registrations_to_apply_payment_to .= '<td class="txn-admin-payment-owing-td jst-cntr">' . __( 'Owing', 'event_espresso' ) . '</td>';
897
		$registrations_to_apply_payment_to .= '<td class="jst-cntr">' . __( 'Apply', 'event_espresso' ) . '</td>';
898
		$registrations_to_apply_payment_to .= '</tr></thead><tbody>';
899
		// get registrations for TXN
900
		$registrations = $this->_transaction->registrations( $query_params );
901
		foreach ( $registrations as $registration ) {
902
			if ( $registration instanceof EE_Registration ) {
903
				$owing = $registration->final_price() - $registration->paid();
904
				$taxable = $registration->ticket()->taxable() ? ' <span class="smaller-text lt-grey-text"> ' . __( '+ tax', 'event_espresso' ) . '</span>' : '';
905
				$checked = empty( $existing_reg_payments ) || in_array( $registration->ID(), $existing_reg_payments ) ? ' checked="checked"' : '';
0 ignored issues
show
Bug introduced by
The variable $existing_reg_payments seems to never exist, and therefore empty should always return true. 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...
906
				$registrations_to_apply_payment_to .= '<tr id="apply-payment-registration-row-' . $registration->ID() . '">';
907
				// add html for checkbox input and label
908
				$registrations_to_apply_payment_to .= '<td>' . $registration->ID() . '</td>';
909
				$registrations_to_apply_payment_to .= '<td>' . $registration->attendee() instanceof EE_Attendee ? $registration->attendee()->full_name() : __( 'Unknown Attendee', 'event_espresso' ) . '</td>';
910
				$registrations_to_apply_payment_to .= '<td>' . $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable . '</td>';
911
				$registrations_to_apply_payment_to .= '<td>' . $registration->event_name() . '</td>';
912
				$registrations_to_apply_payment_to .= '<td class="txn-admin-payment-paid-td jst-rght">' . $registration->pretty_paid() . '</td>';
913
				$registrations_to_apply_payment_to .= '<td class="txn-admin-payment-owing-td jst-rght">' . EEH_Template::format_currency( $owing ) . '</td>';
914
				$registrations_to_apply_payment_to .= '<td class="jst-cntr">';
915
				$disabled = $registration->final_price() > 0 ? '' : ' disabled';
916
				$registrations_to_apply_payment_to .= '<input type="checkbox" value="' . $registration->ID() . '" name="txn_admin_payment[registrations]"' . $checked . $disabled . '>';
917
				$registrations_to_apply_payment_to .= '</td>';
918
				$registrations_to_apply_payment_to .= '</tr>';
919
			}
920
		}
921
		$registrations_to_apply_payment_to .= '</tbody></table></div>';
922
		$registrations_to_apply_payment_to .= '<p class="clear description">' . __( '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.', 'event_espresso' ) . '</p></div>';
923
		$this->_template_args[ 'registrations_to_apply_payment_to' ] = $registrations_to_apply_payment_to;
924
	}
925
926
927
928
	/**
929
	 * _get_reg_status_selection
930
	 *
931
	 * @todo this will need to be adjusted either once MER comes along OR we move default reg status to tickets instead of events.
932
	 *	@access protected
933
	 * @return void
934
	 */
935
	protected function _get_reg_status_selection() {
936
		//first get all possible statuses
937
		$statuses = EEM_Registration::reg_status_array(array(), TRUE);
938
		//let's add a "don't change" option.
939
		$status_array['NAN'] = __('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...
940
		$status_array = array_merge( $status_array, $statuses );
941
		$this->_template_args['status_change_select'] = EEH_Form_Fields::select_input( 'txn_reg_status_change[reg_status]', $status_array, 'NAN', 'id="txn-admin-payment-reg-status-inp"', 'txn-reg-status-change-reg-status' );
942
		$this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input( 'delete_txn_reg_status_change[reg_status]', $status_array, 'NAN', 'delete-txn-admin-payment-reg-status-inp', 'delete-txn-reg-status-change-reg-status' );
943
944
	}
945
946
947
948
	/**
949
	 * 	_get_payment_methods
950
	 * Gets all the payment methods available generally, or the ones that are already
951
	 * selected on these payments (in case their payment methods are no longer active).
952
	 * Has the side-effect of updating the template args' payment_methods item
953
	 *	@access private
954
	 * @param EE_Payment[] to show on this page
955
	 *	@return void
956
	 */
957
	private function _get_payment_methods( $payments = array() ) {
958
		$payment_methods_of_payments = array();
959
		foreach( $payments as $payment ){
960
			if( $payment instanceof EE_Payment ){
961
				$payment_methods_of_payments[] = $payment->get( 'PMD_ID' );
962
			}
963
		}
964
		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...
965
			$query_args = array( array( 'OR*payment_method_for_payment' => array(
966
					'PMD_ID' => array( 'IN', $payment_methods_of_payments ),
967
					'PMD_scope' => array( 'LIKE', '%' . EEM_Payment_Method::scope_admin . '%' ) ) ) );
968
		}else{
969
			$query_args = array( array( 'PMD_scope' => array( 'LIKE', '%' . EEM_Payment_Method::scope_admin . '%' ) ) );
970
		}
971
		$this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all( $query_args );
972
	}
973
974
975
976
	/**
977
	 * txn_attendees_meta_box
978
	 *    generates HTML for the Attendees Transaction main meta box
979
	 *
980
	 * @access public
981
	 * @param WP_Post $post
982
	 * @param array $metabox
983
	 * @return void
984
	 */
985
	public function txn_attendees_meta_box( $post, $metabox = array( 'args' => array() )) {
986
987
		extract( $metabox['args'] );
988
		$this->_template_args['post'] = $post;
989
		$this->_template_args['event_attendees'] = array();
990
		// process items in cart
991
		$line_items = $this->_transaction->get_many_related('Line_Item', array( array( 'LIN_type' => 'line-item' ) ) );
992
		if ( ! empty( $line_items )) {
993
			foreach ( $line_items as $item ) {
994
				if ( $item instanceof EE_Line_Item ) {
995
					switch( $item->OBJ_type() ) {
996
997
						case 'Event' :
998
							break;
999
1000
						case 'Ticket' :
1001
							$ticket = $item->ticket();
1002
							if ( empty( $ticket )) {
1003
								continue; //right now we're only handling tickets here.  Cause its expected that only tickets will have attendees right?
1004
							}
1005
							$ticket_price = EEH_Template::format_currency( $item->get( 'LIN_unit_price' ));
1006
							$event = $ticket->get_first_related('Registration')->get_first_related('Event');
1007
							$event_name = $event instanceof EE_Event ? $event->get('EVT_name') . ' - ' . $item->get('LIN_name') : '';
1008
1009
							$registrations = $ticket->get_many_related('Registration', array( array('TXN_ID' => $this->_transaction->ID() )));
1010
							foreach( $registrations as $registration ) {
1011
								$this->_template_args['event_attendees'][$registration->ID()]['att_num'] 						= $registration->get('REG_count');
1012
								$this->_template_args['event_attendees'][$registration->ID()]['event_ticket_name'] 	= $event_name;
1013
								$this->_template_args['event_attendees'][$registration->ID()]['ticket_price'] 				= $ticket_price;
1014
								// attendee info
1015
								$attendee = $registration->get_first_related('Attendee');
1016
								if ( $attendee instanceof EE_Attendee ) {
1017
									$this->_template_args['event_attendees'][$registration->ID()]['att_id'] 			= $attendee->ID();
1018
									$this->_template_args['event_attendees'][$registration->ID()]['attendee'] 	= $attendee->full_name();
1019
									$this->_template_args['event_attendees'][$registration->ID()]['email'] 			= '<a href="mailto:' . $attendee->email() . '?subject=' . $event->get('EVT_name') . __(' Event', 'event_espresso') . '">' . $attendee->email() . '</a>';
1020
									$this->_template_args['event_attendees'][$registration->ID()]['address'] 		=  implode(',<br>', $attendee->full_address_as_array() );
1021
								} else {
1022
									$this->_template_args['event_attendees'][$registration->ID()]['att_id'] 			= '';
1023
									$this->_template_args['event_attendees'][$registration->ID()]['attendee'] 	= '';
1024
									$this->_template_args['event_attendees'][$registration->ID()]['email'] 			= '';
1025
									$this->_template_args['event_attendees'][$registration->ID()]['address'] 		= '';
1026
								}
1027
							}
1028
							break;
1029
1030
					}
1031
				}
1032
			}
1033
1034
			$this->_template_args['transaction_form_url'] = add_query_arg( array( 'action' => 'edit_transaction', 'process' => 'attendees'  ), TXN_ADMIN_URL );
1035
			echo EEH_Template::display_template( TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php', $this->_template_args, TRUE );
1036
1037
		} else {
1038
			echo sprintf(
1039
				__( '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s', 'event_espresso' ),
1040
				'<p class="important-notice">',
1041
				'</p>'
1042
			);
1043
		}
1044
	}
1045
1046
1047
1048
	/**
1049
	 * txn_registrant_side_meta_box
1050
	 * generates HTML for the Edit Transaction side meta box
1051
	 *
1052
	 * @access public
1053
	 * @throws \EE_Error
1054
	 * @return void
1055
	 */
1056
	public function txn_registrant_side_meta_box() {
1057
		$primary_att = $this->_transaction->primary_registration() instanceof EE_Registration ? $this->_transaction->primary_registration()->get_first_related('Attendee') : null;
1058
		if ( ! $primary_att instanceof EE_Attendee ) {
1059
			$this->_template_args['no_attendee_message'] = __('There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.', 'event_espresso');
1060
			$primary_att = EEM_Attendee::instance()->create_default_object();
1061
		}
1062
		$this->_template_args['ATT_ID'] 						= $primary_att->ID();
1063
		$this->_template_args['prime_reg_fname']		= $primary_att->fname();
0 ignored issues
show
Documentation Bug introduced by
The method fname does not exist on object<EE_Base_Class>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1064
		$this->_template_args['prime_reg_lname']		= $primary_att->lname();
0 ignored issues
show
Documentation Bug introduced by
The method lname does not exist on object<EE_Base_Class>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1065
		$this->_template_args['prime_reg_email'] 		= $primary_att->email();
0 ignored issues
show
Documentation Bug introduced by
The method email does not exist on object<EE_Base_Class>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1066
		$this->_template_args['prime_reg_phone'] 	= $primary_att->phone();
0 ignored issues
show
Documentation Bug introduced by
The method phone does not exist on object<EE_Base_Class>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1067
		$this->_template_args['edit_attendee_url'] 	= EE_Admin_Page::add_query_args_and_nonce( array( 'action' => 'edit_attendee', 'post' => $primary_att->ID()  ), REG_ADMIN_URL );
1068
		// get formatted address for registrant
1069
		$this->_template_args[ 'formatted_address' ] = EEH_Address::format( $primary_att );
1070
		echo EEH_Template::display_template( TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php', $this->_template_args, TRUE );
1071
	}
1072
1073
1074
1075
	/**
1076
	 * txn_billing_info_side_meta_box
1077
	 * 	generates HTML for the Edit Transaction side meta box
1078
	*
1079
	 * @access public
1080
	*	@return void
1081
	*/
1082
	public function txn_billing_info_side_meta_box() {
1083
1084
		$this->_template_args['billing_form'] = $this->_transaction->billing_info();
1085
		$this->_template_args['billing_form_url'] = add_query_arg(
1086
			array( 'action' => 'edit_transaction', 'process' => 'billing'  ),
1087
			TXN_ADMIN_URL
1088
		);
1089
1090
		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1091
		echo EEH_Template::display_template( $template_path, $this->_template_args, TRUE );/**/
1092
	}
1093
1094
1095
1096
	/**
1097
	 * apply_payments_or_refunds
1098
	 * 	registers a payment or refund made towards a transaction
1099
	*
1100
	 * @access public
1101
	*	@return void
1102
	*/
1103
	public function apply_payments_or_refunds() {
1104
		$json_response_data = array( 'return_data' => FALSE );
1105
		$valid_data = $this->_validate_payment_request_data();
1106
		if ( ! empty( $valid_data ) ) {
1107
			$PAY_ID = $valid_data[ 'PAY_ID' ];
1108
			//save  the new payment
1109
			$payment = $this->_create_payment_from_request_data( $valid_data );
1110
			// get the TXN for this payment
1111
			$transaction = $payment->transaction();
1112
			// verify transaction
1113
			if ( $transaction instanceof EE_Transaction ) {
1114
				// calculate_total_payments_and_update_status
1115
				$this->_process_transaction_payments( $transaction );
1116
				$REG_IDs = $this->_get_REG_IDs_to_apply_payment_to( $payment );
1117
				$this->_remove_existing_registration_payments( $payment, $PAY_ID );
1118
				// apply payment to registrations (if applicable)
1119
				if ( ! empty( $REG_IDs ) ) {
1120
					$this->_update_registration_payments( $transaction, $payment, $REG_IDs );
1121
					$this->_maybe_send_notifications();
1122
					// now process status changes for the same registrations
1123
					$this->_process_registration_status_change( $transaction, $REG_IDs );
1124
				}
1125
				$this->_maybe_send_notifications( $payment );
1126
				//prepare to render page
1127
				$json_response_data[ 'return_data' ] = $this->_build_payment_json_response( $payment, $REG_IDs );
1128
				do_action( 'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording', $transaction, $payment );
1129
			} else {
1130
				EE_Error::add_error(
1131
					__( 'A valid Transaction for this payment could not be retrieved.', 'event_espresso' ),
1132
					__FILE__, __FUNCTION__, __LINE__
1133
				);
1134
			}
1135
		} else {
1136
			EE_Error::add_error( __( 'The payment form data could not be processed. Please try again.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
1137
		}
1138
1139
		$notices = EE_Error::get_notices( false, false, false );
1140
		$this->_template_args = array(
1141
			'data' => $json_response_data,
1142
			'error' => $notices['errors'],
1143
			'success' => $notices['success']
1144
		);
1145
		$this->_return_json();
1146
	}
1147
1148
1149
1150
	/**
1151
	 * _validate_payment_request_data
1152
	 *
1153
	 * @return array
1154
	 */
1155
	protected function _validate_payment_request_data() {
1156
		if ( ! isset( $this->_req_data[ 'txn_admin_payment' ] ) ) {
1157
			return false;
1158
		}
1159
		$payment_form = $this->_generate_payment_form_section();
1160
		try {
1161
			if ( $payment_form->was_submitted() ) {
1162
				$payment_form->receive_form_submission();
1163
				if ( ! $payment_form->is_valid() ) {
1164
					$submission_error_messages = array();
1165
					foreach ( $payment_form->get_validation_errors_accumulated() as $validation_error ) {
1166 View Code Duplication
						if ( $validation_error instanceof EE_Validation_Error ) {
1167
							$submission_error_messages[] = sprintf(
1168
								_x( '%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso' ),
1169
								$validation_error->get_form_section()->html_label_text(),
1170
								$validation_error->getMessage()
1171
							);
1172
						}
1173
					}
1174
					EE_Error::add_error( join( '<br />', $submission_error_messages ), __FILE__, __FUNCTION__, __LINE__ );
1175
					return array();
1176
				}
1177
			}
1178
		} catch ( EE_Error $e ) {
1179
			EE_Error::add_error( $e->getMessage(), __FILE__, __FUNCTION__, __LINE__ );
1180
			return array();
1181
		}
1182
		return $payment_form->valid_data();
1183
	}
1184
1185
1186
1187
	/**
1188
	 * _generate_payment_form_section
1189
	 *
1190
	 * @return EE_Form_Section_Proper
1191
	 */
1192
	protected function _generate_payment_form_section() {
1193
		return new EE_Form_Section_Proper(
1194
			array(
1195
				'name' => 'txn_admin_payment',
1196
				'subsections'     => array(
1197
					'PAY_ID' => new EE_Text_Input(
1198
						array(
1199
							'default' => 0,
1200
							'required' => false,
1201
							'html_label_text' => __( 'Payment ID', 'event_espresso' ),
1202
							'validation_strategies' => array( new EE_Int_Normalization() )
1203
						)
1204
					),
1205
					'TXN_ID' => new EE_Text_Input(
1206
						array(
1207
							'default' => 0,
1208
							'required' => true,
1209
							'html_label_text' => __( 'Transaction ID', 'event_espresso' ),
1210
							'validation_strategies' => array( new EE_Int_Normalization() )
1211
						)
1212
					),
1213
					'type' => new EE_Text_Input(
1214
						array(
1215
							'default' => 1,
1216
							'required' => true,
1217
							'html_label_text' => __( 'Payment or Refund', 'event_espresso' ),
1218
							'validation_strategies' => array( new EE_Int_Normalization() )
1219
						)
1220
					),
1221
					'amount' => new EE_Text_Input(
1222
						array(
1223
							'default' => 0,
1224
							'required' => true,
1225
							'html_label_text' => __( 'Payment amount', 'event_espresso' ),
1226
							'validation_strategies' => array( new EE_Float_Normalization() )
1227
						)
1228
					),
1229
					'status' => new EE_Text_Input(
1230
						array(
1231
							'default' => EEM_Payment::status_id_approved,
1232
							'required' => true,
1233
							'html_label_text' => __( 'Payment status', 'event_espresso' ),
1234
						)
1235
					),
1236
					'PMD_ID' => new EE_Text_Input(
1237
						array(
1238
							'default' => 2,
1239
							'required' => true,
1240
							'html_label_text' => __( 'Payment Method', 'event_espresso' ),
1241
							'validation_strategies' => array( new EE_Int_Normalization() )
1242
						)
1243
					),
1244
					'date' => new EE_Text_Input(
1245
						array(
1246
							'default' => time(),
1247
							'required' => true,
1248
							'html_label_text' => __( 'Payment date', 'event_espresso' ),
1249
						)
1250
					),
1251
					'txn_id_chq_nmbr' => new EE_Text_Input(
1252
						array(
1253
							'default' => '',
1254
							'required' => false,
1255
							'html_label_text' => __( 'Transaction or Cheque Number', 'event_espresso' ),
1256
                                                        'validation_strategies' => array(
1257
                                                            new EE_Max_Length_Validation_Strategy( __('Input too long', 'event_espresso'), 100 ),
1258
                                                        )
1259
						)
1260
					),
1261
					'po_number' => new EE_Text_Input(
1262
						array(
1263
							'default' => '',
1264
							'required' => false,
1265
							'html_label_text' => __( 'Purchase Order Number', 'event_espresso' ),
1266
                                                        'validation_strategies' => array(
1267
                                                            new EE_Max_Length_Validation_Strategy( __('Input too long', 'event_espresso'), 100 ),
1268
                                                        )
1269
						)
1270
					),
1271
					'accounting' => new EE_Text_Input(
1272
						array(
1273
							'default' => '',
1274
							'required' => false,
1275
							'html_label_text' => __( 'Extra Field for Accounting', 'event_espresso' ),
1276
                                                        'validation_strategies' => array(
1277
                                                            new EE_Max_Length_Validation_Strategy( __('Input too long', 'event_espresso'), 100 ),
1278
                                                        )
1279
						)
1280
					),
1281
				)
1282
			)
1283
		);
1284
	}
1285
1286
1287
1288
	/**
1289
	 * _create_payment_from_request_data
1290
	 *
1291
	 * @param array $valid_data
1292
	 * @return EE_Payment
1293
	 */
1294
	protected function _create_payment_from_request_data( $valid_data ) {
1295
		$PAY_ID = $valid_data[ 'PAY_ID' ];
1296
		// get payment amount
1297
		$amount = $valid_data[ 'amount' ] ? abs( $valid_data[ 'amount' ] ) : 0;
1298
		// payments have a type value of 1 and refunds have a type value of -1
1299
		// so multiplying amount by type will give a positive value for payments, and negative values for refunds
1300
		$amount = $valid_data[ 'type' ] < 0 ? $amount * -1 : $amount;
1301
		// for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1302
		$date = $valid_data['date'] ? preg_replace( '/\s+/', ' ', $valid_data['date'] ) : date( 'Y-m-d g:i a', current_time( 'timestamp' ) );
1303
		$payment = EE_Payment::new_instance(
1304
			array(
1305
				'TXN_ID' 								=> $valid_data[ 'TXN_ID' ],
1306
				'STS_ID' 								=> $valid_data[ 'status' ],
1307
				'PAY_timestamp' 				=> $date,
1308
				'PAY_source'           			=> EEM_Payment_Method::scope_admin,
1309
				'PMD_ID'               				=> $valid_data[ 'PMD_ID' ],
1310
				'PAY_amount'           			=> $amount,
1311
				'PAY_txn_id_chq_nmbr'  	=> $valid_data[ 'txn_id_chq_nmbr' ],
1312
				'PAY_po_number'        		=> $valid_data[ 'po_number' ],
1313
				'PAY_extra_accntng'    		=> $valid_data[ 'accounting' ],
1314
				'PAY_details'          				=> $valid_data,
1315
				'PAY_ID'               				=> $PAY_ID
1316
			),
1317
			'',
1318
			array( 'Y-m-d', 'g:i a' )
1319
		);
1320
1321
		if ( ! $payment->save() ) {
1322
			EE_Error::add_error(
1323
				sprintf(
1324
					__( 'Payment %1$d has not been successfully saved to the database.', 'event_espresso' ),
1325
					$payment->ID()
1326
				),
1327
				__FILE__, __FUNCTION__, __LINE__
1328
			);
1329
		}
1330
		return $payment;
1331
	}
1332
1333
1334
1335
	/**
1336
	 * _process_transaction_payments
1337
	 *
1338
	 * @param \EE_Transaction $transaction
1339
	 * @return array
1340
	 */
1341
	protected function _process_transaction_payments( EE_Transaction $transaction ) {
1342
		/** @type EE_Transaction_Payments $transaction_payments */
1343
		$transaction_payments = EE_Registry::instance()->load_class( 'Transaction_Payments' );
1344
		//update the transaction with this payment
1345
		if ( $transaction_payments->calculate_total_payments_and_update_status( $transaction ) ) {
1346
			EE_Error::add_success( __( 'The payment has been processed successfully.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
1347
		} else {
1348
			EE_Error::add_error(
1349
				__( 'The payment was processed successfully but the amount paid for the transaction was not updated.', 'event_espresso' )
1350
				, __FILE__, __FUNCTION__, __LINE__
1351
			);
1352
		}
1353
	}
1354
1355
1356
1357
	/**
1358
	 * _get_REG_IDs_to_apply_payment_to
1359
	 *
1360
	 * returns a list of registration IDs that the payment will apply to
1361
	 *
1362
	 * @param \EE_Payment $payment
1363
	 * @return array
1364
	 */
1365
	protected function _get_REG_IDs_to_apply_payment_to( EE_Payment $payment ) {
1366
		$REG_IDs = array();
1367
		// grab array of IDs for specific registrations to apply changes to
1368
		if ( isset( $this->_req_data[ 'txn_admin_payment' ][ 'registrations' ] ) ) {
1369
			$REG_IDs = (array)$this->_req_data[ 'txn_admin_payment' ][ 'registrations' ];
1370
		}
1371
		//nothing specified ? then get all reg IDs
1372
		if ( empty( $REG_IDs ) ) {
1373
			$registrations = $payment->transaction()->registrations();
1374
			$REG_IDs = ! empty( $registrations ) ? array_keys( $registrations ) : $this->_get_existing_reg_payment_REG_IDs( $payment );
1375
		}
1376
		// ensure that REG_IDs are integers and NOT strings
1377
		return array_map( 'intval', $REG_IDs );
1378
	}
1379
1380
1381
1382
	/**
1383
	 * @return array
1384
	 */
1385
	public function existing_reg_payment_REG_IDs() {
1386
		return $this->_existing_reg_payment_REG_IDs;
1387
	}
1388
1389
1390
1391
	/**
1392
	 * @param array $existing_reg_payment_REG_IDs
1393
	 */
1394
	public function set_existing_reg_payment_REG_IDs( $existing_reg_payment_REG_IDs = null ) {
1395
		$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...
1396
	}
1397
1398
1399
1400
	/**
1401
	 * _get_existing_reg_payment_REG_IDs
1402
	 *
1403
	 * returns a list of registration IDs that the payment is currently related to
1404
	 * as recorded in the database
1405
	 *
1406
	 * @param \EE_Payment $payment
1407
	 * @return array
1408
	 */
1409
	protected function _get_existing_reg_payment_REG_IDs( EE_Payment $payment ) {
1410
		if ( $this->existing_reg_payment_REG_IDs() === null ) {
1411
			// let's get any existing reg payment records for this payment
1412
			$existing_reg_payment_REG_IDs = $payment->get_many_related( 'Registration' );
1413
			// but we only want the REG IDs, so grab the array keys
1414
			$existing_reg_payment_REG_IDs = ! empty( $existing_reg_payment_REG_IDs ) ? array_keys( $existing_reg_payment_REG_IDs ) : array();
1415
			$this->set_existing_reg_payment_REG_IDs( $existing_reg_payment_REG_IDs );
1416
		}
1417
		return $this->existing_reg_payment_REG_IDs();
1418
	}
1419
1420
1421
1422
	/**
1423
	 * _remove_existing_registration_payments
1424
	 *
1425
	 * this calculates the difference between existing relations
1426
	 * to the supplied payment and the new list registration IDs,
1427
	 * removes any related registrations that no longer apply,
1428
	 * and then updates the registration paid fields
1429
	 *
1430
	 * @param \EE_Payment $payment
1431
	 * @param int         $PAY_ID
1432
	 * @return bool;
0 ignored issues
show
Documentation introduced by
The doc-type bool; could not be parsed: Expected "|" or "end of type", but got ";" at position 4. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1433
	 */
1434
	protected function _remove_existing_registration_payments( EE_Payment $payment, $PAY_ID = 0 ) {
1435
		// newly created payments will have nothing recorded for $PAY_ID
1436
		if ( $PAY_ID == 0 ) {
1437
			return false;
1438
		}
1439
		$existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs( $payment );
1440
		if ( empty( $existing_reg_payment_REG_IDs )) {
1441
			return false;
1442
		}
1443
		/** @type EE_Transaction_Payments $transaction_payments */
1444
		$transaction_payments = EE_Registry::instance()->load_class( 'Transaction_Payments' );
1445
		return $transaction_payments->delete_registration_payments_and_update_registrations(
1446
			$payment,
1447
			array(
1448
				array(
1449
					'PAY_ID' => $payment->ID(),
1450
					'REG_ID' => array( 'IN', $existing_reg_payment_REG_IDs ),
1451
				)
1452
			)
1453
		);
1454
	}
1455
1456
1457
1458
	/**
1459
	 * _update_registration_payments
1460
	 *
1461
	 * this applies the payments to the selected registrations
1462
	 * but only if they have not already been paid for
1463
	 *
1464
	 * @param  EE_Transaction $transaction
1465
	 * @param \EE_Payment $payment
1466
	 * @param array $REG_IDs
1467
	 * @return bool
1468
	 */
1469
	protected function _update_registration_payments( EE_Transaction $transaction, EE_Payment $payment, $REG_IDs = array() ) {
1470
		// we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
1471
		// so let's do that using our set of REG_IDs from the form
1472
		$registration_query_where_params = array(
1473
			'REG_ID' => array( 'IN', $REG_IDs )
1474
		);
1475
		// but add in some conditions regarding payment,
1476
		// so that we don't apply payments to registrations that are free or have already been paid for
1477
		// but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
1478
		if ( ! $payment->is_a_refund() ) {
1479
			$registration_query_where_params[ 'REG_final_price' ]  = array( '!=', 0 );
1480
			$registration_query_where_params[ 'REG_final_price*' ]  = array( '!=', 'REG_paid', true );
1481
		}
1482
		//EEH_Debug_Tools::printr( $registration_query_where_params, '$registration_query_where_params', __FILE__, __LINE__ );
1483
		$registrations = $transaction->registrations( array( $registration_query_where_params ) );
1484
		if ( ! empty( $registrations ) ) {
1485
			/** @type EE_Payment_Processor $payment_processor */
1486
			$payment_processor = EE_Registry::instance()->load_core( 'Payment_Processor' );
1487
			$payment_processor->process_registration_payments( $transaction, $payment, $registrations );
0 ignored issues
show
Documentation introduced by
$registrations is of type array<integer,object<EE_Base_Class>>, but the function expects a array<integer,object<EE_Registration>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1488
		}
1489
	}
1490
1491
1492
1493
	/**
1494
	 * _process_registration_status_change
1495
	 *
1496
	 * This processes requested registration status changes for all the registrations
1497
	 * on a given transaction and (optionally) sends out notifications for the changes.
1498
	 *
1499
	 * @param  EE_Transaction $transaction
1500
	 * @param array $REG_IDs
1501
	 * @return bool
1502
	 */
1503
	protected function _process_registration_status_change( EE_Transaction $transaction, $REG_IDs = array() ) {
1504
		// first if there is no change in status then we get out.
1505
		if (
1506
			! isset( $this->_req_data['txn_reg_status_change'], $this->_req_data[ 'txn_reg_status_change' ][ 'reg_status' ] )
1507
			|| $this->_req_data['txn_reg_status_change']['reg_status'] == 'NAN'
1508
		) {
1509
			//no error message, no change requested, just nothing to do man.
1510
			return FALSE;
1511
		}
1512
		/** @type EE_Transaction_Processor $transaction_processor */
1513
		$transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' );
1514
		// made it here dude?  Oh WOW.  K, let's take care of changing the statuses
1515
		return $transaction_processor->manually_update_registration_statuses(
1516
			$transaction,
1517
			sanitize_text_field( $this->_req_data[ 'txn_reg_status_change' ][ 'reg_status' ] ),
1518
			array( array( 'REG_ID' => array( 'IN', $REG_IDs ) ) )
1519
		);
1520
	}
1521
1522
1523
1524
	/**
1525
	 * _build_payment_json_response
1526
	 *
1527
	 * @access public
1528
	 * @param \EE_Payment $payment
1529
	 * @param array       $REG_IDs
1530
	 * @param bool | null        $delete_txn_reg_status_change
1531
	 * @return array
1532
	 */
1533
	protected function _build_payment_json_response( EE_Payment $payment, $REG_IDs = array(), $delete_txn_reg_status_change = null ) {
1534
		// was the payment deleted ?
1535
		if ( is_bool( $delete_txn_reg_status_change )) {
1536
			return array(
1537
				'PAY_ID' 				=> $payment->ID(),
1538
				'amount' 			=> $payment->amount(),
1539
				'total_paid' 			=> $payment->transaction()->paid(),
1540
				'txn_status' 			=> $payment->transaction()->status_ID(),
1541
				'pay_status' 		=> $payment->STS_ID(),
1542
				'registrations' 	=> $this->_registration_payment_data_array( $REG_IDs ),
1543
				'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
1544
			);
1545
		} else {
1546
			$this->_get_payment_status_array();
1547
			return array(
1548
				'amount' 		=> $payment->amount(),
1549
				'total_paid' 		=> $payment->transaction()->paid(),
1550
				'txn_status' 		=> $payment->transaction()->status_ID(),
1551
				'pay_status' 	=> $payment->STS_ID(),
1552
				'PAY_ID'           => $payment->ID(),
1553
				'STS_ID' 			=> $payment->STS_ID(),
1554
				'status' 			=> self::$_pay_status[ $payment->STS_ID() ],
1555
				'date' 				=> $payment->timestamp( 'Y-m-d', 'h:i a' ),
1556
				'method' 		=> strtoupper( $payment->source() ),
1557
				'PM_ID' 			=> $payment->payment_method() ? $payment->payment_method()->ID() : 1,
1558
				'gateway' 		=> $payment->payment_method() ? $payment->payment_method()->admin_name() : __( "Unknown", 'event_espresso' ),
1559
				'gateway_response' 	=> $payment->gateway_response(),
1560
				'txn_id_chq_nmbr'  	=> $payment->txn_id_chq_nmbr(),
1561
				'po_number'        		=> $payment->po_number(),
1562
				'extra_accntng'    		=> $payment->extra_accntng(),
1563
				'registrations'    			=> $this->_registration_payment_data_array( $REG_IDs ),
1564
			);
1565
		}
1566
	}
1567
1568
1569
1570
	/**
1571
	 * delete_payment
1572
	 * 	delete a payment or refund made towards a transaction
1573
	*
1574
	 * @access public
1575
	*	@return void
1576
	*/
1577
	public function delete_payment() {
1578
		$json_response_data = array( 'return_data' => FALSE );
1579
		$PAY_ID = isset( $this->_req_data['delete_txn_admin_payment'], $this->_req_data['delete_txn_admin_payment']['PAY_ID'] ) ? absint( $this->_req_data['delete_txn_admin_payment']['PAY_ID'] ) : 0;
1580
		if ( $PAY_ID ) {
1581
			$delete_txn_reg_status_change = isset( $this->_req_data[ 'delete_txn_reg_status_change' ] ) ? $this->_req_data[ 'delete_txn_reg_status_change' ] : false;
1582
			$payment = EEM_Payment::instance()->get_one_by_ID( $PAY_ID );
1583
			if ( $payment instanceof EE_Payment ) {
1584
				$REG_IDs = $this->_get_existing_reg_payment_REG_IDs( $payment );
1585
				/** @type EE_Transaction_Payments $transaction_payments */
1586
				$transaction_payments = EE_Registry::instance()->load_class( 'Transaction_Payments' );
1587
				if ( $transaction_payments->delete_payment_and_update_transaction( $payment )) {
1588
					$json_response_data['return_data'] = $this->_build_payment_json_response( $payment, $REG_IDs, $delete_txn_reg_status_change );
1589
					if ( $delete_txn_reg_status_change ) {
1590
						$this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
1591
						//MAKE sure we also add the delete_txn_req_status_change to the
1592
						//$_REQUEST global because that's how messages will be looking for it.
1593
						$_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
1594
						$this->_maybe_send_notifications();
1595
						$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...
1596
					}
1597
				}
1598
			} else {
1599
				EE_Error::add_error(
1600
					__( 'Valid Payment data could not be retrieved from the database.', 'event_espresso' ),
1601
					__FILE__, __FUNCTION__, __LINE__
1602
				);
1603
			}
1604
		} else {
1605
			EE_Error::add_error(
1606
				__( 'A valid Payment ID was not received, therefore payment form data could not be loaded.', 'event_espresso' ),
1607
				__FILE__, __FUNCTION__, __LINE__
1608
			);
1609
		}
1610
		$notices = EE_Error::get_notices( false, false, false);
1611
		$this->_template_args = array(
1612
			'data' => $json_response_data,
1613
			'success' => $notices['success'],
1614
			'error' => $notices['errors'],
1615
			'attention' => $notices['attention']
1616
		);
1617
		$this->_return_json();
1618
	}
1619
1620
1621
1622
	/**
1623
	 * _registration_payment_data_array
1624
	 * adds info for 'owing' and 'paid' for each registration to the json response
1625
	 *
1626
	 * @access protected
1627
	 * @param array $REG_IDs
1628
	 * @return array
1629
	 */
1630
	protected function _registration_payment_data_array( $REG_IDs ) {
1631
		$registration_payment_data = array();
1632
		//if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
1633
		if ( ! empty( $REG_IDs ) ) {
1634
			$registrations = EEM_Registration::instance()->get_all( array( array( 'REG_ID' => array( 'IN', $REG_IDs ) ) ) );
1635
			foreach ( $registrations as $registration ) {
1636
				if ( $registration instanceof EE_Registration ) {
1637
					$registration_payment_data[ $registration->ID() ] = array(
1638
						'paid' => $registration->pretty_paid(),
1639
						'owing' => EEH_Template::format_currency( $registration->final_price() - $registration->paid() ),
1640
					);
1641
				}
1642
			}
1643
		}
1644
		return $registration_payment_data;
1645
	}
1646
1647
1648
1649
	/**
1650
	 * _maybe_send_notifications
1651
	 *
1652
	 * determines whether or not the admin has indicated that notifications should be sent.
1653
	 * If so, will toggle a filter switch for delivering registration notices.
1654
	 * If passed an EE_Payment object, then it will trigger payment notifications instead.
1655
	 *
1656
	 * @access protected
1657
	 * @param \EE_Payment | null $payment
1658
	 */
1659
	protected function _maybe_send_notifications( $payment = null ) {
1660
		switch ( $payment instanceof EE_Payment ) {
1661
			// payment notifications
1662 View Code Duplication
			case true :
1663
				if (
1664
					isset(
1665
						$this->_req_data[ 'txn_payments' ],
1666
						$this->_req_data[ 'txn_payments' ][ 'send_notifications' ]
1667
					) &&
1668
					filter_var( $this->_req_data[ 'txn_payments' ][ 'send_notifications' ], FILTER_VALIDATE_BOOLEAN )
1669
				) {
1670
					$this->_process_payment_notification( $payment );
1671
				}
1672
				break;
1673
			// registration notifications
1674 View Code Duplication
			case false :
1675
				if (
1676
					isset(
1677
						$this->_req_data[ 'txn_reg_status_change' ],
1678
						$this->_req_data[ 'txn_reg_status_change' ][ 'send_notifications' ]
1679
					) &&
1680
					filter_var( $this->_req_data[ 'txn_reg_status_change' ][ 'send_notifications' ], FILTER_VALIDATE_BOOLEAN )
1681
				) {
1682
					add_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true' );
1683
				}
1684
				break;
1685
		}
1686
	}
1687
1688
1689
1690
	/**
1691
	 * _send_payment_reminder
1692
	 * 	generates HTML for the View Transaction Details Admin page
1693
	*
1694
	 * @access protected
1695
	*	@return void
1696
	*/
1697
	protected function _send_payment_reminder() {
1698
	    $TXN_ID = ( ! empty( $this->_req_data['TXN_ID'] )) ? absint( $this->_req_data['TXN_ID'] ) : FALSE;
1699
		$transaction = EEM_Transaction::instance()->get_one_by_ID( $TXN_ID );
1700
		$query_args = isset($this->_req_data['redirect_to'] ) ? array('action' => $this->_req_data['redirect_to'], 'TXN_ID' => $this->_req_data['TXN_ID'] ) : array();
1701
		do_action( 'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder', $transaction );
1702
		$this->_redirect_after_action( FALSE, __('payment reminder', 'event_espresso'), __('sent', 'event_espresso'), $query_args, TRUE );
0 ignored issues
show
Documentation introduced by
FALSE is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1703
	}
1704
1705
1706
1707
	/**
1708
	 *  get_transactions
1709
	 *    get transactions for given parameters (used by list table)
1710
	 *
1711
	 * @param  int     $perpage how many transactions displayed per page
1712
	 * @param  boolean $count return the count or objects
1713
	 * @param string   $view
1714
	 * @return mixed int = count || array of transaction objects
1715
	 */
1716
	public function get_transactions( $perpage, $count = FALSE, $view = '' ) {
1717
1718
		$TXN = EEM_Transaction::instance();
1719
1720
	    $start_date = isset( $this->_req_data['txn-filter-start-date'] ) ? wp_strip_all_tags( $this->_req_data['txn-filter-start-date'] ) : date( 'm/d/Y', strtotime( '-10 year' ));
1721
	    $end_date = isset( $this->_req_data['txn-filter-end-date'] ) ? wp_strip_all_tags( $this->_req_data['txn-filter-end-date'] ) : date( 'm/d/Y' );
1722
1723
	    //make sure our timestamps start and end right at the boundaries for each day
1724
	    $start_date = date( 'Y-m-d', strtotime( $start_date ) ) . ' 00:00:00';
1725
	    $end_date = date( 'Y-m-d', strtotime( $end_date ) ) . ' 23:59:59';
1726
1727
1728
	    //convert to timestamps
1729
	    $start_date = strtotime( $start_date );
1730
	    $end_date = strtotime( $end_date );
1731
1732
	    //makes sure start date is the lowest value and vice versa
1733
	    $start_date = min( $start_date, $end_date );
1734
	    $end_date = max( $start_date, $end_date );
1735
1736
	    //convert to correct format for query
1737
	$start_date = EEM_Transaction::instance()->convert_datetime_for_query( 'TXN_timestamp', date( 'Y-m-d H:i:s', $start_date ), 'Y-m-d H:i:s' );
1738
	$end_date = EEM_Transaction::instance()->convert_datetime_for_query( 'TXN_timestamp', date( 'Y-m-d H:i:s', $end_date ), 'Y-m-d H:i:s' );
1739
1740
1741
1742
	    //set orderby
1743
		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
1744
1745
		switch ( $this->_req_data['orderby'] ) {
1746
			case 'TXN_ID':
1747
				$orderby = 'TXN_ID';
1748
				break;
1749
			case 'ATT_fname':
1750
				$orderby = 'Registration.Attendee.ATT_fname';
1751
				break;
1752
			case 'event_name':
1753
				$orderby = 'Registration.Event.EVT_name';
1754
				break;
1755
			default: //'TXN_timestamp'
1756
				$orderby = 'TXN_timestamp';
1757
		}
1758
1759
		$sort = ( isset( $this->_req_data['order'] ) && ! empty( $this->_req_data['order'] )) ? $this->_req_data['order'] : 'DESC';
1760
		$current_page = isset( $this->_req_data['paged'] ) && !empty( $this->_req_data['paged'] ) ? $this->_req_data['paged'] : 1;
1761
		$per_page = isset( $perpage ) && !empty( $perpage ) ? $perpage : 10;
1762
		$per_page = isset( $this->_req_data['perpage'] ) && !empty( $this->_req_data['perpage'] ) ? $this->_req_data['perpage'] : $per_page;
1763
1764
		$offset = ($current_page-1)*$per_page;
1765
		$limit = array( $offset, $per_page );
1766
1767
		$_where = array(
1768
			'TXN_timestamp' => array('BETWEEN', array($start_date, $end_date) ),
1769
			'Registration.REG_count' => 1
1770
		);
1771
1772
		if ( isset( $this->_req_data['EVT_ID'] ) ) {
1773
			$_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
1774
		}
1775
1776
		if ( isset( $this->_req_data['s'] ) ) {
1777
			$search_string = '%' . $this->_req_data['s'] . '%';
1778
			$_where['OR'] = array(
1779
				'Registration.Event.EVT_name' => array( 'LIKE', $search_string ),
1780
				'Registration.Event.EVT_desc' => array( 'LIKE', $search_string ),
1781
				'Registration.Event.EVT_short_desc' => array( 'LIKE' , $search_string ),
1782
				'Registration.Attendee.ATT_full_name' => array( 'LIKE', $search_string ),
1783
				'Registration.Attendee.ATT_fname' => array( 'LIKE', $search_string ),
1784
				'Registration.Attendee.ATT_lname' => array( 'LIKE', $search_string ),
1785
				'Registration.Attendee.ATT_short_bio' => array( 'LIKE', $search_string ),
1786
				'Registration.Attendee.ATT_email' => array('LIKE', $search_string ),
1787
				'Registration.Attendee.ATT_address' => array( 'LIKE', $search_string ),
1788
				'Registration.Attendee.ATT_address2' => array( 'LIKE', $search_string ),
1789
				'Registration.Attendee.ATT_city' => array( 'LIKE', $search_string ),
1790
				'Registration.REG_final_price' => array( 'LIKE', $search_string ),
1791
				'Registration.REG_code' => array( 'LIKE', $search_string ),
1792
				'Registration.REG_count' => array( 'LIKE' , $search_string ),
1793
				'Registration.REG_group_size' => array( 'LIKE' , $search_string ),
1794
				'Registration.Ticket.TKT_name' => array( 'LIKE', $search_string ),
1795
				'Registration.Ticket.TKT_description' => array( 'LIKE', $search_string ),
1796
				'Payment.PAY_source' => array('LIKE', $search_string ),
1797
				'Payment.Payment_Method.PMD_name' => array('LIKE', $search_string ),
1798
				'TXN_session_data' => array( 'LIKE', $search_string ),
1799
				'Payment.PAY_txn_id_chq_nmbr' => array( 'LIKE', $search_string )
1800
				);
1801
		}
1802
1803
		//failed transactions
1804
		$failed = ( ! empty( $this->_req_data['status'] ) && $this->_req_data['status'] == 'failed' && ! $count ) || ( $count && $view == 'failed' ) ? TRUE: FALSE;
1805
		$abandoned = ( ! empty( $this->_req_data['status'] ) && $this->_req_data['status'] == 'abandoned' && ! $count ) || ( $count && $view == 'abandoned' ) ? TRUE: FALSE;
1806
1807
		if ( $failed ) {
1808
			$_where[ 'STS_ID' ] = EEM_Transaction::failed_status_code;
1809
		} else if ( $abandoned ) {
1810
				$_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
1811
		} else {
1812
				$_where['STS_ID'] = array( '!=', EEM_Transaction::failed_status_code );
1813
				$_where['STS_ID*'] = array( '!=', EEM_Transaction::abandoned_status_code );
1814
		}
1815
1816
		$query_params = array( $_where, 'order_by' => array( $orderby => $sort ), 'limit' => $limit );
1817
1818
		$transactions = $count ? $TXN->count( array($_where), 'TXN_ID', TRUE ) : $TXN->get_all($query_params);
1819
1820
1821
		return $transactions;
1822
1823
	}
1824
1825
1826
1827
}
1828