Give_Export_Donations_CSV   F
last analyzed

Complexity

Total Complexity 107

Size/Duplication

Total Lines 565
Duplicated Lines 9.03 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 51
loc 565
rs 2
c 0
b 0
f 0
wmc 107
lcom 1
cbo 4

8 Methods

Rating   Name   Duplication   Size   Complexity  
D set_properties() 0 23 10
B get_form_ids() 0 11 8
A csv_cols() 0 13 3
D get_cols() 8 96 25
B get_donation_argument() 0 28 7
F get_data() 14 212 44
A get_percentage_complete() 0 17 4
B print_csv_rows() 29 29 6

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 Give_Export_Donations_CSV 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 Give_Export_Donations_CSV, and based on these observations, apply Extract Interface, too.

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, WordImpress
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...
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
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'] ) && ( 'all' !== $request['give_price_option'] && '' !== $request['give_price_option'] ) ? absint( $request['give_price_option'] ) : null;
100
		$this->start      = isset( $request['start'] ) ? sanitize_text_field( $request['start'] ) : '';
101
		$this->end        = isset( $request['end'] ) ? sanitize_text_field( $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 'donation_total':
203
					$cols['donation_total'] = __( 'Donation Total', 'give' );
204
					break;
205
				case 'currency_code':
206
					$cols['currency_code'] = __( 'Currency Code', 'give' );
207
					break;
208
				case 'currency_symbol':
209
					$cols['currency_symbol'] = __( 'Currency Symbol', 'give' );
210
					break;
211
				case 'donation_status':
212
					$cols['donation_status'] = __( 'Donation Status', 'give' );
213
					break;
214
				case 'payment_gateway':
215
					$cols['payment_gateway'] = __( 'Payment Gateway', 'give' );
216
				case 'payment_mode':
217
					$cols['payment_mode'] = __( 'Payment Mode', 'give' );
218
					break;
219
				case 'form_id':
220
					$cols['form_id'] = __( 'Form ID', 'give' );
221
					break;
222
				case 'form_title':
223
					$cols['form_title'] = __( 'Form Title', 'give' );
224
					break;
225
				case 'form_level_id':
226
					$cols['form_level_id'] = __( 'Level ID', 'give' );
227
					break;
228
				case 'form_level_title':
229
					$cols['form_level_title'] = __( 'Level Title', 'give' );
230
					break;
231
				case 'donation_date':
232
					$cols['donation_date'] = __( 'Donation Date', 'give' );
233
					break;
234
				case 'donation_time':
235
					$cols['donation_time'] = __( 'Donation Time', 'give' );
236
					break;
237
				case 'userid':
238
					$cols['userid'] = __( 'User ID', 'give' );
239
					break;
240
				case 'donorid':
241
					$cols['donorid'] = __( 'Donor ID', 'give' );
242
					break;
243
				case 'donor_ip':
244
					$cols['donor_ip'] = __( 'Donor IP Address', 'give' );
245
					break;
246
				default:
247
					$cols[ $key ] = $key;
248
249
			}
250
		}
251
252
		/**
253
		 * Filter to get columns name when exporting donation
254
		 *
255
		 * @since 2.1
256
		 *
257
		 * @param array $cols columns name for CSV
258
		 * @param array $columns columns select by admin to export
259
		 */
260
		return (array) apply_filters( 'give_export_donation_get_columns_name', $cols, $columns );
261
	}
262
263
	/**
264
	 * Get the donation argument
265
	 *
266
	 * @since 2.1
267
	 *
268
	 * @param array $args donation argument
269
	 *
270
	 * @return array $args donation argument
271
	 */
272
	public function get_donation_argument( $args = array() ) {
273
		$defaults = array(
274
			'number' => 30,
275
			'page'   => $this->step,
276
			'status' => $this->status,
277
		);
278
		// Date query.
279
		if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
280
			if ( ! empty( $this->start ) ) {
281
				$defaults['date_query'][0]['after'] = date( 'Y-n-d 00:00:00', strtotime( $this->start ) );
282
			}
283
			if ( ! empty( $this->end ) ) {
284
				$defaults['date_query'][0]['before'] = date( 'Y-n-d 00:00:00', strtotime( $this->end ) );
285
			}
286
		}
287
288
		if ( ! empty( $this->form_id ) ) {
289
			$defaults['give_forms'] = is_array( $this->form_id ) ? $this->form_id : array( $this->form_id );
290
		}
291
292
		/**
293
		 * Filter to modify Payment Query arguments for exporting
294
		 * donations.
295
		 *
296
		 * @since 2.1.3
297
		 */
298
		return apply_filters( 'give_export_donations_donation_query_args', wp_parse_args( $args, $defaults ) );
299
	}
300
301
	/**
302
	 * Get the Export Data.
303
	 *
304
	 * @access public
305
	 *
306
	 * @since  2.1
307
	 *
308
	 * @global object $wpdb Used to query the database using the WordPress database API.
309
	 *
310
	 * @return array $data The data for the CSV file.
311
	 */
312
	public function get_data() {
313
314
		$data = array();
315
		$i    = 0;
316
		// Payment query.
317
		$payments = give_get_payments( $this->get_donation_argument() );
318
319
		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...
320
321
			foreach ( $payments as $payment ) {
322
323
				$columns      = $this->csv_cols();
324
				$payment      = new Give_Payment( $payment->ID );
325
				$payment_meta = $payment->payment_meta;
326
				$address      = $payment->address;
327
328
				// Set columns.
329
				if ( ! empty( $columns['donation_id'] ) ) {
330
					$data[ $i ]['donation_id'] = $payment->ID;
331
				}
332
333
				if ( ! empty( $columns['seq_id'] ) ) {
334
					$data[ $i ]['seq_id'] = Give()->seq_donation_number->get_serial_code( $payment->ID );
335
				}
336
337
				if ( ! empty( $columns['title_prefix'] ) ) {
338
					$data[ $i ]['title_prefix'] = ! empty( $payment->title_prefix ) ? $payment->title_prefix : '';
339
				}
340
341 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...
342
					$data[ $i ]['first_name'] = isset( $payment->first_name ) ? $payment->first_name : '';
343
				}
344
345 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...
346
					$data[ $i ]['last_name'] = isset( $payment->last_name ) ? $payment->last_name : '';
347
				}
348
349
				if ( ! empty( $columns['email'] ) ) {
350
					$data[ $i ]['email'] = $payment->email;
351
				}
352
353
				if ( ! empty( $columns['company'] ) ) {
354
					$data[ $i ]['company'] = empty( $payment_meta['_give_donation_company'] ) ? '' : str_replace( "\'", "'", $payment_meta['_give_donation_company'] );
355
				}
356
357 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...
358
					$data[ $i ]['address_line1']   = isset( $address['line1'] ) ? $address['line1'] : '';
359
					$data[ $i ]['address_line2']   = isset( $address['line2'] ) ? $address['line2'] : '';
360
					$data[ $i ]['address_city']    = isset( $address['city'] ) ? $address['city'] : '';
361
					$data[ $i ]['address_state']   = isset( $address['state'] ) ? $address['state'] : '';
362
					$data[ $i ]['address_zip']     = isset( $address['zip'] ) ? $address['zip'] : '';
363
					$data[ $i ]['address_country'] = isset( $address['country'] ) ? $address['country'] : '';
364
				}
365
366
				if ( ! empty( $columns['donation_total'] ) ) {
367
					$data[ $i ]['donation_total'] = give_format_amount( give_donation_amount( $payment->ID ) );
368
				}
369
370
				if ( ! empty( $columns['currency_code'] ) ) {
371
					$data[ $i ]['currency_code'] = empty( $payment_meta['_give_payment_currency'] ) ? give_get_currency() : $payment_meta['_give_payment_currency'];
372
				}
373
374
				if ( ! empty( $columns['currency_symbol'] ) ) {
375
					$currency_code                 = $data[ $i ]['currency_code'];
376
					$data[ $i ]['currency_symbol'] = give_currency_symbol( $currency_code, true );
377
				}
378
379
				if ( ! empty( $columns['donation_status'] ) ) {
380
					$data[ $i ]['donation_status'] = give_get_payment_status( $payment, true );
381
				}
382
383
				if ( ! empty( $columns['payment_gateway'] ) ) {
384
					$data[ $i ]['payment_gateway'] = $payment->gateway;
385
				}
386
387
				if ( ! empty( $columns['payment_mode'] ) ) {
388
					$data[ $i ]['payment_mode'] = $payment->mode;
389
				}
390
391
				if ( ! empty( $columns['form_id'] ) ) {
392
					$data[ $i ]['form_id'] = $payment->form_id;
393
				}
394
395
				if ( ! empty( $columns['form_title'] ) ) {
396
					$data[ $i ]['form_title'] = get_the_title( $payment->form_id );
397
				}
398
399
				if ( ! empty( $columns['form_level_id'] ) ) {
400
					$data[ $i ]['form_level_id'] = $payment->price_id;
401
				}
402
403
				if ( ! empty( $columns['form_level_title'] ) ) {
404
					$var_prices = give_has_variable_prices( $payment->form_id );
405
					if ( empty( $var_prices ) ) {
406
						$data[ $i ]['form_level_title'] = '';
407
					} else {
408
						if ( 'custom' === $payment->price_id ) {
409
							$custom_amount_text = give_get_meta( $payment->form_id, '_give_custom_amount_text', true );
410
411
							if ( empty( $custom_amount_text ) ) {
412
								$custom_amount_text = esc_html__( 'Custom', 'give' );
413
							}
414
							$data[ $i ]['form_level_title'] = $custom_amount_text;
415
						} else {
416
							$data[ $i ]['form_level_title'] = give_get_price_option_name( $payment->form_id, $payment->price_id );
417
						}
418
					}
419
				}
420
421
				if ( ! empty( $columns['donation_date'] ) ) {
422
					$payment_date                = strtotime( $payment->date );
423
					$data[ $i ]['donation_date'] = date( give_date_format(), $payment_date );
424
				}
425
426
				if ( ! empty( $columns['donation_time'] ) ) {
427
					$payment_date                = strtotime( $payment->date );
428
					$data[ $i ]['donation_time'] = date_i18n( 'H', $payment_date ) . ':' . date( 'i', $payment_date );
429
				}
430
431
				if ( ! empty( $columns['userid'] ) ) {
432
					$data[ $i ]['userid'] = $payment->user_id;
433
				}
434
435
				if ( ! empty( $columns['donorid'] ) ) {
436
					$data[ $i ]['donorid'] = $payment->customer_id;
437
				}
438
439
				if ( ! empty( $columns['donor_ip'] ) ) {
440
					$data[ $i ]['donor_ip'] = give_get_payment_user_ip( $payment->ID );
441
				}
442
443
				// Add custom field data.
444
				// First we remove the standard included keys from above.
445
				$remove_keys = array(
446
					'donation_id',
447
					'seq_id',
448
					'first_name',
449
					'last_name',
450
					'email',
451
					'address_line1',
452
					'address_line2',
453
					'address_city',
454
					'address_state',
455
					'address_zip',
456
					'address_country',
457
					'donation_total',
458
					'payment_gateway',
459
					'payment_mode',
460
					'form_id',
461
					'form_title',
462
					'form_level_id',
463
					'form_level_title',
464
					'donation_date',
465
					'donation_time',
466
					'userid',
467
					'donorid',
468
					'donor_ip',
469
				);
470
471
				// Removing above keys...
472
				foreach ( $remove_keys as $key ) {
473
					unset( $columns[ $key ] );
474
				}
475
476
				// Now loop through remaining meta fields.
477
				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...
478
					$field_data         = get_post_meta( $payment->ID, $col, true );
479
					$data[ $i ][ $col ] = $field_data;
480
					unset( $columns[ $col ] );
481
				}
482
483
				/**
484
				 * Filter to modify Donation CSV data when exporting donation
485
				 *
486
				 * @since 2.1
487
				 *
488
				 * @param array Donation data
489
				 * @param Give_Payment $payment Instance of Give_Payment
490
				 * @param array $columns Donation data $columns that are not being merge
491
				 * @param Give_Export_Donations_CSV $this Instance of Give_Export_Donations_CSV
492
				 *
493
				 * @return array Donation data
494
				 */
495
				$data[ $i ] = apply_filters( 'give_export_donation_data', $data[ $i ], $payment, $columns, $this );
496
497
				$new_data = array();
498
				$old_data = $data[ $i ];
499
500
				// sorting the columns bas on row
501
				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...
502
					if ( array_key_exists( $key, $old_data ) ) {
503
						$new_data[ $key ] = $old_data[ $key ];
504
					}
505
				}
506
507
				$data[ $i ] = $new_data;
508
509
				// Increment iterator.
510
				$i ++;
511
512
			}
513
514
			$data = apply_filters( 'give_export_get_data', $data );
515
			$data = apply_filters( "give_export_get_data_{$this->export_type}", $data );
516
517
			return $data;
518
519
		}
520
521
		return array();
522
523
	}
524
525
	/**
526
	 * Return the calculated completion percentage.
527
	 *
528
	 * @since 2.1
529
	 *
530
	 * @return int
531
	 */
532
	public function get_percentage_complete() {
533
		$args = $this->get_donation_argument( array( 'number' => - 1 ) );
534
		if ( isset( $args['page'] ) ) {
535
			unset( $args['page'] );
536
		}
537
		$query      = give_get_payments( $args );
538
		$total      = count( $query );
539
		$percentage = 100;
540
		if ( $total > 0 ) {
541
			$percentage = ( ( 30 * $this->step ) / $total ) * 100;
542
		}
543
		if ( $percentage > 100 ) {
544
			$percentage = 100;
545
		}
546
547
		return $percentage;
548
	}
549
550
	/**
551
	 * Print the CSV rows for the current step.
552
	 *
553
	 * @access public
554
	 *
555
	 * @since  2.1
556
	 *
557
	 * @return string|false
558
	 */
559 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...
560
561
		$row_data = '';
562
		$data     = $this->get_data();
563
		$cols     = $this->get_csv_cols();
564
565
		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...
566
567
			// Output each row
568
			foreach ( $data as $row ) {
569
				$i = 1;
570
				foreach ( $row as $col_id => $column ) {
571
					// Make sure the column is valid
572
					if ( array_key_exists( $col_id, $cols ) ) {
573
						$row_data .= '"' . preg_replace( '/"/', "'", $column ) . '"';
574
						$row_data .= $i == count( $cols ) ? '' : ',';
575
						$i ++;
576
					}
577
				}
578
				$row_data .= "\r\n";
579
			}
580
581
			$this->stash_step_data( $row_data );
582
583
			return $row_data;
584
		}
585
586
		return false;
587
	}
588
}
589