Give_Export_Donations_CSV::get_cols()   F
last analyzed

Complexity

Conditions 28
Paths 28

Size

Total Lines 106

Duplication

Lines 8
Ratio 7.55 %

Importance

Changes 0
Metric Value
cc 28
nc 28
nop 1
dl 8
loc 106
rs 3.3333
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Payments Export Class.
4
 *
5
 * This class handles payment export in batches.
6
 *
7
 * @package     Give
8
 * @subpackage  Admin/Reports
9
 * @copyright   Copyright (c) 2016, GiveWP
10
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
11
 * @since       2.1
12
 */
13
14
// Exit if accessed directly.
15
if ( ! defined( 'ABSPATH' ) ) {
16
	exit;
17
}
18
19
/**
20
 * Give_Export_Donations_CSV Class
21
 *
22
 * @since 2.1
23
 */
24
class Give_Export_Donations_CSV extends Give_Batch_Export {
25
26
	/**
27
	 * Our export type. Used for export-type specific filters/actions.
28
	 *
29
	 * @since 2.1
30
	 *
31
	 * @var string
32
	 */
33
	public $export_type = 'payments';
34
35
	/**
36
	 * Form submission data.
37
	 *
38
	 * @since 2.1
39
	 *
40
	 * @var array
41
	 */
42
	public $data = array();
43
44
	/**
45
	 * Form submission data.
46
	 *
47
	 * @since 2.1
48
	 *
49
	 * @var array
50
	 */
51
	public $cols = array();
52
53
	/**
54
	 * Form ID.
55
	 *
56
	 * @since 2.1
57
	 *
58
	 * @var string
59
	 */
60
	public $form_id = '';
61
62
	/**
63
	 * Form tags ids.
64
	 *
65
	 * @since 2.1
66
	 *
67
	 * @var array
68
	 */
69
	public $tags = '';
70
71
72
	/**
73
	 * Form categories ids.
74
	 *
75
	 * @since 2.1
76
	 *
77
	 * @var array
78
	 */
79
	public $categories = '';
80
81
	/**
82
	 * Set the properties specific to the export.
83
	 *
84
	 * @since 2.1
85
	 *
86
	 * @param array $request The Form Data passed into the batch processing.
87
	 */
88
	public function set_properties( $request ) {
89
90
		// Set data from form submission
91
		if ( isset( $_POST['form'] ) ) {
92
			$this->data = give_clean( wp_parse_args( $_POST['form'] ) );
0 ignored issues
show
Documentation Bug introduced by
It seems like give_clean(wp_parse_args($_POST['form'])) can also be of type string. However, the property $data is declared as type array. 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...
93
		}
94
95
		$this->form       = $this->data['forms'];
96
		$this->categories = ! empty( $request['give_forms_categories'] ) ? (array) $request['give_forms_categories'] : array();
97
		$this->tags       = ! empty( $request['give_forms_tags'] ) ? (array) $request['give_forms_tags'] : array();
98
		$this->form_id    = $this->get_form_ids( $request );
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->get_form_ids($request) can also be of type array or boolean. However, the property $form_id is declared as type string. 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...
99
		$this->price_id   = isset( $request['give_price_option'] ) && ! in_array( $this->price_id, array( 'all', '' ) ) ? absint( $request['give_price_option'] ) : null;
100
		$this->start      = ! empty( $request['start'] ) ? date( 'Y-m-d', strtotime( $request['start'] ) ) : '';
101
		$this->end        = ! empty( $request['end'] ) ? date( 'Y-m-d', strtotime( $request['end'] ) ) : '';
102
		$this->status     = isset( $request['status'] ) ? sanitize_text_field( $request['status'] ) : 'complete';
103
104
		/**
105
		 * Hook to use after setting properties.
106
		 *
107
		 * @since 2.1.3
108
		 */
109
		do_action( 'give_export_donations_form_data', $this->data );
110
	}
111
112
	/**
113
	 * Get donation form id list
114
	 *
115
	 * @since 2.1
116
	 *
117
	 * @param array $request form data that need to be exported
118
	 *
119
	 * @return array|boolean|null $form get all the donation id that need to be exported
120
	 */
121
	public function get_form_ids( $request = array() ) {
122
		$form = ! empty( $request['forms'] ) && 0 !== $request['forms'] ? absint( $request['forms'] ) : null;
123
124
		$form_ids = ! empty( $request['form_ids'] ) ? sanitize_text_field( $request['form_ids'] ) : null;
125
126
		if ( empty( $form ) && ! empty( $form_ids ) && ( ! empty( $this->categories ) || ! empty( $this->tags ) ) ) {
127
			$form = explode( ',', $form_ids );
128
		}
129
130
		return $form;
131
	}
132
133
	/**
134
	 * Set the CSV columns.
135
	 *
136
	 * @access public
137
	 *
138
	 * @since  2.1
139
	 *
140
	 * @return array|bool $cols All the columns.
141
	 */
142
	public function csv_cols() {
143
144
		$columns = isset( $this->data['give_give_donations_export_option'] ) ? $this->data['give_give_donations_export_option'] : array();
145
146
		// We need columns.
147
		if ( empty( $columns ) ) {
148
			return false;
149
		}
150
151
		$this->cols = $this->get_cols( $columns );
152
153
		return $this->cols;
154
	}
155
156
157
	/**
158
	 * CSV file columns.
159
	 *
160
	 * @since  2.1
161
	 *
162
	 * @param array $columns
163
	 *
164
	 * @return array
165
	 */
166
	private function get_cols( $columns ) {
167
168
		$cols = array();
169
170
		foreach ( $columns as $key => $value ) {
171
172
			switch ( $key ) {
173
				case 'donation_id':
174
					$cols['donation_id'] = __( 'Donation ID', 'give' );
175
					break;
176
				case 'seq_id':
177
					$cols['seq_id'] = __( 'Donation Number', 'give' );
178
					break;
179
				case 'title_prefix':
180
					$cols['title_prefix'] = __( 'Title Prefix', 'give' );
181
					break;
182
				case 'first_name':
183
					$cols['first_name'] = __( 'First Name', 'give' );
184
					break;
185
				case 'last_name':
186
					$cols['last_name'] = __( 'Last Name', 'give' );
187
					break;
188
				case 'email':
189
					$cols['email'] = __( 'Email Address', 'give' );
190
					break;
191
				case 'company':
192
					$cols['company'] = __( 'Company Name', 'give' );
193
					break;
194 View Code Duplication
				case 'address':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
195
					$cols['address_line1']   = __( 'Address 1', 'give' );
196
					$cols['address_line2']   = __( 'Address 2', 'give' );
197
					$cols['address_city']    = __( 'City', 'give' );
198
					$cols['address_state']   = __( 'State', 'give' );
199
					$cols['address_zip']     = __( 'Zip', 'give' );
200
					$cols['address_country'] = __( 'Country', 'give' );
201
					break;
202
				case 'comment':
203
					$cols['comment'] = __( 'Donor Comment', 'give' );
204
					break;
205
				case 'donation_total':
206
					$cols['donation_total'] = __( 'Donation Total', 'give' );
207
					break;
208
				case 'currency_code':
209
					$cols['currency_code'] = __( 'Currency Code', 'give' );
210
					break;
211
				case 'currency_symbol':
212
					$cols['currency_symbol'] = __( 'Currency Symbol', 'give' );
213
					break;
214
				case 'donation_status':
215
					$cols['donation_status'] = __( 'Donation Status', 'give' );
216
					break;
217
				case 'payment_gateway':
218
					$cols['payment_gateway'] = __( 'Payment Gateway', 'give' );
219
					break;
220
				case 'payment_mode':
221
					$cols['payment_mode'] = __( 'Payment Mode', 'give' );
222
					break;
223
				case 'form_id':
224
					$cols['form_id'] = __( 'Form ID', 'give' );
225
					break;
226
				case 'form_title':
227
					$cols['form_title'] = __( 'Form Title', 'give' );
228
					break;
229
				case 'form_level_id':
230
					$cols['form_level_id'] = __( 'Level ID', 'give' );
231
					break;
232
				case 'form_level_title':
233
					$cols['form_level_title'] = __( 'Level Title', 'give' );
234
					break;
235
				case 'donation_date':
236
					$cols['donation_date'] = __( 'Donation Date', 'give' );
237
					break;
238
				case 'donation_time':
239
					$cols['donation_time'] = __( 'Donation Time', 'give' );
240
					break;
241
				case 'userid':
242
					$cols['userid'] = __( 'User ID', 'give' );
243
					break;
244
				case 'donorid':
245
					$cols['donorid'] = __( 'Donor ID', 'give' );
246
					break;
247
				case 'donor_ip':
248
					$cols['donor_ip'] = __( 'Donor IP Address', 'give' );
249
					break;
250
				case 'donation_note_private':
251
					$cols['donation_note_private'] = __( 'Donation Note (private)', 'give' );
252
					break;
253
				case 'donation_note_to_donor':
254
					$cols['donation_note_to_donor'] = __( 'Donation Note (to donor)', 'give' );
255
					break;
256
				default:
257
					$cols[ $key ] = $key;
258
259
			}
260
		}
261
262
		/**
263
		 * Filter to get columns name when exporting donation
264
		 *
265
		 * @since 2.1
266
		 *
267
		 * @param array $cols    columns name for CSV
268
		 * @param array $columns columns select by admin to export
269
		 */
270
		return (array) apply_filters( 'give_export_donation_get_columns_name', $cols, $columns );
271
	}
272
273
	/**
274
	 * Get the donation argument
275
	 *
276
	 * @since 2.1
277
	 *
278
	 * @param array $args donation argument
279
	 *
280
	 * @return array $args donation argument
281
	 */
282
	public function get_donation_argument( $args = array() ) {
283
		$defaults = array(
284
			'number' => 30,
285
			'page'   => $this->step,
286
			'status' => $this->status,
287
		);
288
		// Date query.
289
		if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
290
			if ( ! empty( $this->start ) ) {
291
				$defaults['date_query'][0]['after'] = "{$this->start} 00:00:00";
292
			}
293
			if ( ! empty( $this->end ) ) {
294
				$defaults['date_query'][0]['before'] = "{$this->end} 23:59:59";
295
			}
296
		}
297
298
		if ( ! empty( $this->form_id ) ) {
299
			$defaults['give_forms'] = is_array( $this->form_id ) ? $this->form_id : array( $this->form_id );
300
		}
301
302
		/**
303
		 * Filter to modify Payment Query arguments for exporting
304
		 * donations.
305
		 *
306
		 * @since 2.1.3
307
		 */
308
		return apply_filters( 'give_export_donations_donation_query_args', wp_parse_args( $args, $defaults ) );
309
	}
310
311
	/**
312
	 * Get the Export Data.
313
	 *
314
	 * @access public
315
	 *
316
	 * @since  2.1
317
	 *
318
	 * @global object $wpdb Used to query the database using the WordPress database API.
319
	 *
320
	 * @return array $data The data for the CSV file.
321
	 */
322
	public function get_data() {
323
324
		$data = array();
325
		$i    = 0;
326
		// Payment query.
327
		$payments = give_get_payments( $this->get_donation_argument() );
328
329
		if ( $payments ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $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...
330
331
			foreach ( $payments as $payment ) {
332
333
				$columns      = $this->csv_cols();
334
				$payment      = new Give_Payment( $payment->ID );
335
				$payment_meta = $payment->payment_meta;
336
				$address      = $payment->address;
337
338
				// Set columns.
339
				if ( ! empty( $columns['donation_id'] ) ) {
340
					$data[ $i ]['donation_id'] = $payment->ID;
341
				}
342
343
				if ( ! empty( $columns['seq_id'] ) ) {
344
					$data[ $i ]['seq_id'] = Give()->seq_donation_number->get_serial_code( $payment->ID );
345
				}
346
347
				if ( ! empty( $columns['title_prefix'] ) ) {
348
					$data[ $i ]['title_prefix'] = ! empty( $payment->title_prefix ) ? $payment->title_prefix : '';
349
				}
350
351 View Code Duplication
				if ( ! empty( $columns['first_name'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
352
					$data[ $i ]['first_name'] = isset( $payment->first_name ) ? $payment->first_name : '';
353
				}
354
355 View Code Duplication
				if ( ! empty( $columns['last_name'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
356
					$data[ $i ]['last_name'] = isset( $payment->last_name ) ? $payment->last_name : '';
357
				}
358
359
				if ( ! empty( $columns['email'] ) ) {
360
					$data[ $i ]['email'] = $payment->email;
361
				}
362
363
				if ( ! empty( $columns['company'] ) ) {
364
					$data[ $i ]['company'] = empty( $payment_meta['_give_donation_company'] ) ? '' : str_replace( "\'", "'", $payment_meta['_give_donation_company'] );
365
				}
366
367 View Code Duplication
				if ( ! empty( $columns['address_line1'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
368
					$data[ $i ]['address_line1']   = isset( $address['line1'] ) ? $address['line1'] : '';
369
					$data[ $i ]['address_line2']   = isset( $address['line2'] ) ? $address['line2'] : '';
370
					$data[ $i ]['address_city']    = isset( $address['city'] ) ? $address['city'] : '';
371
					$data[ $i ]['address_state']   = isset( $address['state'] ) ? $address['state'] : '';
372
					$data[ $i ]['address_zip']     = isset( $address['zip'] ) ? $address['zip'] : '';
373
					$data[ $i ]['address_country'] = isset( $address['country'] ) ? $address['country'] : '';
374
				}
375
376
				if ( ! empty( $columns['comment'] ) ) {
377
					$comment               = give_get_donor_donation_comment( $payment->ID, $payment->donor_id );
378
					$data[ $i ]['comment'] = ! empty( $comment ) ? $comment->comment_content : '';
379
				}
380
381
				if ( ! empty( $columns['donation_total'] ) ) {
382
					$data[ $i ]['donation_total'] = give_format_amount( give_donation_amount( $payment->ID ) );
383
				}
384
385
				if ( ! empty( $columns['currency_code'] ) ) {
386
					$data[ $i ]['currency_code'] = empty( $payment_meta['_give_payment_currency'] ) ? give_get_currency() : $payment_meta['_give_payment_currency'];
387
				}
388
389
				if ( ! empty( $columns['currency_symbol'] ) ) {
390
					$currency_code                 = $data[ $i ]['currency_code'];
391
					$data[ $i ]['currency_symbol'] = give_currency_symbol( $currency_code, true );
392
				}
393
394
				if ( ! empty( $columns['donation_status'] ) ) {
395
					$data[ $i ]['donation_status'] = give_get_payment_status( $payment, true );
396
				}
397
398
				if ( ! empty( $columns['payment_gateway'] ) ) {
399
					$data[ $i ]['payment_gateway'] = $payment->gateway;
400
				}
401
402
				if ( ! empty( $columns['payment_mode'] ) ) {
403
					$data[ $i ]['payment_mode'] = $payment->mode;
404
				}
405
406
				if ( ! empty( $columns['form_id'] ) ) {
407
					$data[ $i ]['form_id'] = $payment->form_id;
408
				}
409
410
				if ( ! empty( $columns['form_title'] ) ) {
411
					$data[ $i ]['form_title'] = get_the_title( $payment->form_id );
412
				}
413
414
				if ( ! empty( $columns['form_level_id'] ) ) {
415
					$data[ $i ]['form_level_id'] = $payment->price_id;
416
				}
417
418
				if ( ! empty( $columns['form_level_title'] ) ) {
419
					$var_prices = give_has_variable_prices( $payment->form_id );
420
					if ( empty( $var_prices ) ) {
421
						$data[ $i ]['form_level_title'] = '';
422
					} else {
423
						if ( 'custom' === $payment->price_id ) {
424
							$custom_amount_text = give_get_meta( $payment->form_id, '_give_custom_amount_text', true );
425
426
							if ( empty( $custom_amount_text ) ) {
427
								$custom_amount_text = esc_html__( 'Custom', 'give' );
428
							}
429
							$data[ $i ]['form_level_title'] = $custom_amount_text;
430
						} else {
431
							$data[ $i ]['form_level_title'] = give_get_price_option_name( $payment->form_id, $payment->price_id );
432
						}
433
					}
434
				}
435
436
				if ( ! empty( $columns['donation_date'] ) ) {
437
					$payment_date                = strtotime( $payment->date );
438
					$data[ $i ]['donation_date'] = date( give_date_format(), $payment_date );
439
				}
440
441
				if ( ! empty( $columns['donation_time'] ) ) {
442
					$payment_date                = strtotime( $payment->date );
443
					$data[ $i ]['donation_time'] = date_i18n( 'H', $payment_date ) . ':' . date( 'i', $payment_date );
444
				}
445
446
				if ( ! empty( $columns['userid'] ) ) {
447
					$data[ $i ]['userid'] = $payment->user_id;
448
				}
449
450
				if ( ! empty( $columns['donorid'] ) ) {
451
					$data[ $i ]['donorid'] = $payment->customer_id;
452
				}
453
454
				if ( ! empty( $columns['donor_ip'] ) ) {
455
					$data[ $i ]['donor_ip'] = give_get_payment_user_ip( $payment->ID );
456
				}
457
458
				if ( ! empty( $columns['donation_note_private'] ) ) {
459
					$comments = Give()->comment->db->get_comments( array(
460
						'comment_parent' => $payment->ID,
461
						'comment_type'   => 'donation',
462
						'meta_query'     => array(
463
							'relation' => 'OR',
464
							array(
465
								'key'     => 'note_type',
466
								'compare' => 'NOT EXISTS',
467
							),
468
							array(
469
								'key'     => 'note_type',
470
								'value'   => 'donor',
471
								'compare' => '!=',
472
							),
473
						),
474
					) );
475
476
					$comment_html = array();
477
478 View Code Duplication
					if ( ! empty( $comments ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
479
						foreach ( $comments as $comment ) {
480
							$comment_html[] = sprintf(
481
								'%s - %s',
482
								date( 'Y-m-d', strtotime( $comment->comment_date ) ),
483
								$comment->comment_content
484
							);
485
						}
486
					}
487
488
					$data[ $i ]['donation_note_private'] = implode( "\n", $comment_html );
489
				}
490
491
				if ( ! empty( $columns['donation_note_to_donor'] ) ) {
492
					$comments = Give()->comment->db->get_comments( array(
493
						'comment_parent' => $payment->ID,
494
						'comment_type'   => 'donation',
495
						'meta_query'     => array(
496
							array(
497
								'key'     => 'note_type',
498
								'value'   => 'donor',
499
							),
500
						),
501
					) );
502
503
					$comment_html = array();
504
505 View Code Duplication
					if ( ! empty( $comments ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
506
						foreach ( $comments as $comment ) {
507
							$comment_html[] = sprintf(
508
								'%s - %s',
509
								date( 'Y-m-d', strtotime( $comment->comment_date ) ),
510
								$comment->comment_content
511
							);
512
						}
513
					}
514
					$data[ $i ]['donation_note_to_donor'] = implode( "\n", $comment_html );
515
				}
516
517
				// Add custom field data.
518
				// First we remove the standard included keys from above.
519
				$remove_keys = array(
520
					'donation_id',
521
					'seq_id',
522
					'first_name',
523
					'last_name',
524
					'email',
525
					'address_line1',
526
					'address_line2',
527
					'address_city',
528
					'address_state',
529
					'address_zip',
530
					'address_country',
531
					'donation_total',
532
					'payment_gateway',
533
					'payment_mode',
534
					'form_id',
535
					'form_title',
536
					'form_level_id',
537
					'form_level_title',
538
					'donation_date',
539
					'donation_time',
540
					'userid',
541
					'donorid',
542
					'donor_ip',
543
				);
544
545
				// Removing above keys...
546
				foreach ( $remove_keys as $key ) {
547
					unset( $columns[ $key ] );
548
				}
549
550
				// Now loop through remaining meta fields.
551
				foreach ( $columns as $col ) {
0 ignored issues
show
Bug introduced by
The expression $columns of type false|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
552
					$field_data         = get_post_meta( $payment->ID, $col, true );
553
					$data[ $i ][ $col ] = $field_data;
554
					unset( $columns[ $col ] );
555
				}
556
557
				/**
558
				 * Filter to modify Donation CSV data when exporting donation
559
				 *
560
				 * @since 2.1
561
				 *
562
				 * @param array Donation data
563
				 * @param Give_Payment              $payment Instance of Give_Payment
564
				 * @param array                     $columns Donation data $columns that are not being merge
565
				 * @param Give_Export_Donations_CSV $this    Instance of Give_Export_Donations_CSV
566
				 *
567
				 * @return array Donation data
568
				 */
569
				$data[ $i ] = apply_filters( 'give_export_donation_data', $data[ $i ], $payment, $columns, $this );
570
571
				$new_data = array();
572
				$old_data = $data[ $i ];
573
574
				// sorting the columns bas on row
575
				foreach ( $this->csv_cols() as $key => $value ) {
0 ignored issues
show
Bug introduced by
The expression $this->csv_cols() of type false|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
576
					if ( array_key_exists( $key, $old_data ) ) {
577
						$new_data[ $key ] = $old_data[ $key ];
578
					}
579
				}
580
581
				$data[ $i ] = $new_data;
582
583
				// Increment iterator.
584
				$i ++;
585
586
			}
587
588
			$data = apply_filters( 'give_export_get_data', $data );
589
			$data = apply_filters( "give_export_get_data_{$this->export_type}", $data );
590
591
			return $data;
592
593
		}
594
595
		return array();
596
597
	}
598
599
	/**
600
	 * Return the calculated completion percentage.
601
	 *
602
	 * @since 2.1
603
	 *
604
	 * @return int
605
	 */
606
	public function get_percentage_complete() {
607
		$args = $this->get_donation_argument( array( 'number' => - 1, 'output' => '' ) );
608
		if ( isset( $args['page'] ) ) {
609
			unset( $args['page'] );
610
		}
611
		$query      = give_get_payments( $args );
612
		$total      = count( $query );
613
		$percentage = 100;
614
		if ( $total > 0 ) {
615
			$percentage = ( ( 30 * $this->step ) / $total ) * 100;
616
		}
617
		if ( $percentage > 100 ) {
618
			$percentage = 100;
619
		}
620
621
		return $percentage;
622
	}
623
624
	/**
625
	 * Print the CSV rows for the current step.
626
	 *
627
	 * @access public
628
	 *
629
	 * @since  2.1
630
	 *
631
	 * @return string|false
632
	 */
633 View Code Duplication
	public function print_csv_rows() {
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...
634
635
		$row_data = '';
636
		$data     = $this->get_data();
637
		$cols     = $this->get_csv_cols();
638
639
		if ( $data ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data 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...
640
641
			// Output each row
642
			foreach ( $data as $row ) {
643
				$i = 1;
644
				foreach ( $row as $col_id => $column ) {
645
					// Make sure the column is valid
646
					if ( array_key_exists( $col_id, $cols ) ) {
647
						$row_data .= '"' . preg_replace( '/"/', "'", $column ) . '"';
648
						$row_data .= $i == count( $cols ) ? '' : ',';
649
						$i ++;
650
					}
651
				}
652
				$row_data .= "\r\n";
653
			}
654
655
			$this->stash_step_data( $row_data );
656
657
			return $row_data;
658
		}
659
660
		return false;
661
	}
662
}
663