Test Failed
Push — issues/2147 ( f99407 )
by Ravinder
04:53
created

Give_Import_Donations::get_instance()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Donations Import Class
4
 *
5
 * This class handles donations import.
6
 *
7
 * @package     Give
8
 * @subpackage  Classes/Give_Import_Donations
9
 * @copyright   Copyright (c) 2017, WordImpress
10
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
11
 * @since       1.8.14
12
 */
13
14
if ( ! defined( 'ABSPATH' ) ) {
15
	exit; // Exit if accessed directly
16
}
17
18
if ( ! class_exists( 'Give_Import_Donations' ) ) {
19
20
	/**
21
	 * Give_Import_Donations.
22
	 *
23
	 * @since 1.8.14
24
	 */
25
	final class Give_Import_Donations {
26
27
		/**
28
		 * Importer type
29
		 *
30
		 * @since 1.8.13
31
		 * @var string
32
		 */
33
		private $importer_type = 'import_donations';
34
35
		/**
36
		 * Instance.
37
		 *
38
		 * @since
39
		 * @access private
40
		 * @var
41
		 */
42
		static private $instance;
43
44
		/**
45
		 * Importing donation per page.
46
		 *
47
		 * @since 1.8.14
48
		 *
49
		 * @var   int
50
		 */
51
		public static $per_page = 5;
52
53
		/**
54
		 * Singleton pattern.
55
		 *
56
		 * @since
57
		 * @access private
58
		 */
59
		private function __construct() {
60
		}
61
62
63
		/**
64
		 * Get instance.
65
		 *
66
		 * @since
67
		 * @access public
68
		 *
69
		 * @return static
70
		 */
71
		public static function get_instance() {
72
			if ( null === static::$instance ) {
73
				self::$instance = new static();
74
			}
75
76
			return self::$instance;
77
		}
78
79
		/**
80
		 * Setup
81
		 *
82
		 * @since 1.8.14
83
		 *
84
		 * @return void
85
		 */
86
		public function setup() {
87
			$this->setup_hooks();
88
		}
89
90
91
		/**
92
		 * Setup Hooks.
93
		 *
94
		 * @since 1.8.14
95
		 *
96
		 * @return void
97
		 */
98
		private function setup_hooks() {
99
			if ( ! $this->is_donations_import_page() ) {
100
				return;
101
			}
102
103
			// Do not render main import tools page.
104
			remove_action( 'give_admin_field_tools_import', array( 'Give_Settings_Import', 'render_import_field', ) );
105
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
106
107
			// Render donation import page
108
			add_action( 'give_admin_field_tools_import', array( $this, 'render_page' ) );
109
110
			// Print the HTML.
111
			add_action( 'give_tools_import_donations_form_start', array( $this, 'html' ), 10 );
112
113
			// Run when form submit.
114
			add_action( 'give-tools_save_import', array( $this, 'save' ) );
115
116
			add_action( 'give-tools_update_notices', array( $this, 'update_notices' ), 11, 1 );
117
118
			// Used to add submit button.
119
			add_action( 'give_tools_import_donations_form_end', array( $this, 'submit' ), 10 );
120
		}
121
122
123
		/**
124
		 * Update notice
125
		 *
126
		 * @since 1.8.14
127
		 *
128
		 * @param $messages
129
		 *
130
		 * @return mixed
131
		 */
132
		public function update_notices( $messages ) {
133
			if ( ! empty( $_GET['tab'] ) && 'import' === give_clean( $_GET['tab'] ) ) {
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
134
				unset( $messages['give-setting-updated'] );
135
			}
136
137
			return $messages;
138
		}
139
140
		/**
141
		 * Print submit and nonce button.
142
		 *
143
		 * @since 1.8.14
144
		 */
145
		public function submit() {
146
			wp_nonce_field( 'give-save-settings', '_give-save-settings' );
147
			?>
148
			<input type="hidden" class="import-step" id="import-step" name="step" value="<?php echo $this->get_step(); ?>"/>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
149
			<input type="hidden" class="importer-type" value="<?php echo $this->importer_type; ?>"/>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
150
			<?php
151
		}
152
153
		/**
154
		 * Print the HTML for importer.
155
		 *
156
		 * @since 1.8.14
157
		 */
158
		public function html() {
159
			$step = $this->get_step();
160
161
			// Show progress.
162
			$this->render_progress();
163
			?>
164
			<section>
165
				<table class="widefat export-options-table give-table <?php echo "step-{$step}"; ?>" id="<?php echo "step-{$step}"; ?>">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '"step-{$step}"'
Loading history...
166
					<tbody>
167
						<?php
168
						switch ( $this->get_step() ) {
169
							case 1:
170
								$this->render_media_csv();
171
								break;
172
173
							case 2:
174
								$this->render_dropdown();
175
								break;
176
177
							case 3:
178
								$this->start_import();
179
								break;
180
181
							case 4:
182
								$this->import_success();
183
						}
184
185
						if ( false === $this->check_for_dropdown_or_import() ) {
186
							?>
187
							<tr valign="top">
188
								<th></th>
189
								<th>
190
									<input type="submit"
191
										   class="button button-primary button-large button-secondary <?php echo "step-{$step}"; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '"step-{$step}"'
Loading history...
192
										   id="recount-stats-submit"
193
										   value="<?php esc_attr_e( 'Submit', 'give' ); ?>"/>
194
								</th>
195
							</tr>
196
							<?php
197
						}
198
						?>
199
					</tbody>
200
				</table>
201
			</section>
202
			<?php
203
		}
204
205
		/**
206
		 * Show success notice
207
		 *
208
		 * @since 1.8.14
209
		 */
210
		public function import_success() {
211
212
			$delete_csv = ( ! empty( $_GET['delete_csv'] ) ? absint( $_GET['delete_csv'] ) : false );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
213
			$csv        = ( ! empty( $_GET['csv'] ) ? absint( $_GET['csv'] ) : false );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
214
			if ( ! empty( $delete_csv ) && ! empty( $csv ) ) {
215
				wp_delete_attachment( $csv, true );
216
			}
217
218
			$report      = give_import_donation_report();
219
			$report_html = array(
220
				'duplicate_donor'    => array(
221
					__( '%s duplicate %s detected', 'give' ),
222
					__( 'donor', 'give' ),
223
					__( 'donors', 'give' ),
224
				),
225
				'create_donor'       => array(
226
					__( '%s %s created', 'give' ),
227
					__( 'donor', 'give' ),
228
					__( 'donors', 'give' ),
229
				),
230
				'create_form'        => array(
231
					__( '%s donation %s created', 'give' ),
232
					__( 'form', 'give' ),
233
					__( 'forms', 'give' ),
234
				),
235
				'duplicate_donation' => array(
236
					__( '%s duplicate %s detected', 'give' ),
237
					__( 'donation', 'give' ),
238
					__( 'donations', 'give' ),
239
				),
240
				'create_donation'    => array(
241
					__( '%s %s imported', 'give' ),
242
					__( 'donation', 'give' ),
243
					__( 'donations', 'give' ),
244
				),
245
			);
246
			$total       = (int) $_GET['total'];
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-validated input variable: $_GET
Loading history...
247
			-- $total;
248
			$success = (bool) $_GET['success'];
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-validated input variable: $_GET
Loading history...
249
			?>
250
			<tr valign="top" class="give-import-dropdown">
251
				<th colspan="2">
252
					<h2>
253
						<?php
254
						if ( $success ) {
255
							echo sprintf(
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'sprintf'
Loading history...
256
								__( 'Import complete! %s donations processed', 'give' ),
257
								"<strong>{$total}</strong>"
258
							);
259
						} else {
260
							echo sprintf(
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'sprintf'
Loading history...
261
								__( 'Failed to import %s donations', 'give' ),
262
								"<strong>{$total}</strong>"
263
							);
264
						}
265
						?>
266
					</h2>
267
268
					<?php
269
					$text      = __( 'Import Donation', 'give' );
270
					$query_arg = array(
271
						'post_type' => 'give_forms',
272
						'page'      => 'give-tools',
273
						'tab'       => 'import',
274
					);
275
					if ( $success ) {
276
						$query_arg = array(
277
							'post_type' => 'give_forms',
278
							'page'      => 'give-payment-history',
279
						);
280
						$text      = __( 'View Donations', 'give' );
281
					}
282
283
					foreach ( $report as $key => $value ) {
284
						if ( array_key_exists( $key, $report_html ) && ! empty( $value ) ) {
285
							?>
286
							<p>
287
								<?php echo esc_html( wp_sprintf( $report_html[ $key ][0], $value, _n( $report_html[ $key ][1], $report_html[ $key ][2], $value, 'give' ) ) ); ?>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$report_html'
Loading history...
288
							</p>
289
							<?php
290
						}
291
					}
292
					?>
293
294
					<p>
295
						<a class="button button-large button-secondary" href="<?php echo add_query_arg( $query_arg, admin_url( 'edit.php' ) ); ?>"><?php echo $text; ?></a>
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'add_query_arg'
Loading history...
introduced by
Expected next thing to be a escaping function, not '$text'
Loading history...
296
					</p>
297
				</th>
298
			</tr>
299
			<?php
300
		}
301
302
		/**
303
		 * Will start Import
304
		 *
305
		 * @since 1.8.14
306
		 */
307
		public function start_import() {
308
			// Reset the donation form report.
309
			give_import_donation_report_reset();
310
311
			$csv         = (int) $_REQUEST['csv'];
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-validated input variable: $_REQUEST
Loading history...
312
			$index_start = 1;
313
			$index_end   = 1;
0 ignored issues
show
Unused Code introduced by
$index_end is not used, you could remove the assignment.

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

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

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

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

Loading history...
314
			$next        = true;
315
			$total       = self::get_csv_total( $csv );
316
			if ( self::$per_page < $total ) {
317
				$total_ajax = ceil( $total / self::$per_page );
318
				$index_end  = self::$per_page;
319
			} else {
320
				$total_ajax = 1;
321
				$index_end  = $total;
322
				$next       = false;
323
			}
324
			$current_percentage = 100 / ( $total_ajax + 1 );
325
326
			?>
327
			<tr valign="top" class="give-import-dropdown">
328
				<th colspan="2">
329
					<h2 id="give-import-title"><?php esc_html_e( 'Importing', 'give' ) ?></h2>
330
					<p class="give-field-description"><?php esc_html_e( 'Your donations are now being imported...', 'give' ) ?></p>
331
				</th>
332
			</tr>
333
334
			<tr valign="top" class="give-import-dropdown">
335
				<th colspan="2">
336
					<span class="spinner is-active"></span>
337
					<div class="give-progress"
338
						 data-current="1"
339
						 data-total_ajax="<?php echo $total_ajax; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$total_ajax'
Loading history...
340
						 data-start="<?php echo $index_start; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$index_start'
Loading history...
341
						 data-end="<?php echo $index_end; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$index_end'
Loading history...
342
						 data-next="<?php echo $next; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$next'
Loading history...
343
						 data-total="<?php echo $total; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$total'
Loading history...
344
						 data-per_page="<?php echo self::$per_page; ?>">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not 'self'
Loading history...
345
346
						<div style="width: <?php echo $current_percentage; ?>%"></div>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$current_percentage'
Loading history...
347
					</div>
348
					<input type="hidden" value="3" name="step">
349
					<input type="hidden" value='<?php echo maybe_serialize( $_REQUEST['mapto'] ); ?>' name="mapto"
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'maybe_serialize'
Loading history...
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-validated input variable: $_REQUEST
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
350
						   class="mapto">
351
					<input type="hidden" value="<?php echo $_REQUEST['csv']; ?>" name="csv" class="csv">
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Expected next thing to be a escaping function, not '$_REQUEST'
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
352
					<input type="hidden" value="<?php echo $_REQUEST['mode']; ?>" name="mode" class="mode">
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Expected next thing to be a escaping function, not '$_REQUEST'
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
353
					<input type="hidden" value="<?php echo $_REQUEST['create_user']; ?>" name="create_user"
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Expected next thing to be a escaping function, not '$_REQUEST'
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
354
						   class="create_user">
355
					<input type="hidden" value="<?php echo $_REQUEST['delete_csv']; ?>" name="delete_csv"
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Expected next thing to be a escaping function, not '$_REQUEST'
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
356
						   class="delete_csv">
357
					<input type="hidden" value="<?php echo $_REQUEST['delimiter']; ?>" name="delimiter">
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Expected next thing to be a escaping function, not '$_REQUEST'
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
358
					<input type="hidden" value='<?php echo maybe_serialize( self::get_importer( $csv ) ); ?>'
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'maybe_serialize'
Loading history...
359
						   name="main_key"
360
						   class="main_key">
361
				</th>
362
			</tr>
363
364
			<script type="text/javascript">
365
				jQuery(document).ready(function () {
366
					give_on_donation_import_start();
367
				});
368
			</script>
369
			<?php
370
		}
371
372
		/**
373
		 * Will return true if importing can be started or not else false.
374
		 *
375
		 * @since 1.8.14
376
		 */
377
		public function check_for_dropdown_or_import() {
378
			$return = true;
379
			if ( isset( $_REQUEST['mapto'] ) ) {
380
				$mapto = (array) $_REQUEST['mapto'];
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
381
				if ( false === in_array( 'form_title', $mapto ) && false === in_array( 'form_id', $mapto ) ) {
382
					Give_Admin_Settings::add_error( 'give-import-csv-form', __( 'Please select Form ID or Form Name options from the dropdown.', 'give' ) );
383
					$return = false;
384
				}
385
386
				if ( false === in_array( 'amount', $mapto ) ) {
387
					Give_Admin_Settings::add_error( 'give-import-csv-amount', __( 'Please select Amount option from the dropdown.', 'give' ) );
388
					$return = false;
389
				}
390
391
				if ( false === in_array( 'email', $mapto ) && false === in_array( 'donor_id', $mapto ) ) {
392
					Give_Admin_Settings::add_error( 'give-import-csv-donor', __( 'Please select Email id or Customer ID options from the dropdown.', 'give' ) );
393
					$return = false;
394
				}
395
			} else {
396
				$return = false;
397
			}
398
399
			return $return;
400
		}
401
402
		/**
403
		 * Print the Dropdown option for CSV.
404
		 *
405
		 * @since 1.8.14
406
		 */
407
		public function render_dropdown() {
408
			$csv = (int) $_GET['csv'];
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-validated input variable: $_GET
Loading history...
409
410
			// TO check if the CSV files that is being add is valid or not if not then redirect to first step again
411
			if ( ! $this->is_valid_csv( $csv ) ) {
412
				$url = give_import_page_url();
413
				?>
414
				<script type="text/javascript">
415
					window.location = "<?php echo $url; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$url'
Loading history...
416
				</script>
417
				<?php
418
			} else {
419
				?>
420
				<tr valign="top" class="give-import-dropdown">
421
					<th colspan="2">
422
						<h2 id="give-import-title"><?php esc_html_e( 'Map CSV fields to donations', 'give' ) ?></h2>
423
						<p class="give-field-description"><?php esc_html_e( 'Select fields from your CSV file to map against donations fields or to ignore during import.', 'give' ) ?></p>
424
					</th>
425
				</tr>
426
427
				<tr valign="top" class="give-import-dropdown">
428
					<th><b><?php esc_html_e( 'Column name', 'give' ); ?></b></th>
429
					<th><b><?php esc_html_e( 'Map to field', 'give' ); ?></b></th>
430
				</tr>
431
432
				<?php
433
				$raw_key   = $this->get_importer( $csv );
434
				$donations = give_import_donations_options();
435
				$donors    = give_import_donor_options();
436
				$forms     = give_import_donation_form_options();
437
438
				foreach ( $raw_key as $index => $value ) {
0 ignored issues
show
Bug introduced by
The expression $raw_key of type array<integer,string|nul...":"string|null"}>|false 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...
439
					?>
440
					<tr valign="top" class="give-import-option">
441
						<th><?php echo $value; ?></th>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$value'
Loading history...
442
						<th>
443
							<?php
444
							$this->get_columns( $index, $donations, $donors, $forms, $value );
445
							?>
446
						</th>
447
					</tr>
448
					<?php
449
				}
450
			}
451
		}
452
453
		/**
454
		 * @param $option_value
455
		 * @param $value
456
		 *
457
		 * @return string
458
		 */
459
		public function selected( $option_value, $value ) {
460
			$selected = '';
461
			if ( stristr( $value, $option_value ) ) {
462
				$selected = 'selected';
463
			} elseif ( strrpos( $value, '_' ) && stristr( $option_value, 'Import as Meta' ) ) {
464
				$selected = 'selected';
465
			}
466
467
			return $selected;
468
		}
469
470
		/**
471
		 * Print the columns from the CSV.
472
		 *
473
		 * @since 1.8.14
474
		 */
475
		public function get_columns( $index, $donations, $donors, $forms, $value = false ) {
476
			$default = give_import_default_options();
477
			?>
478
			<select name="mapto[<?php echo $index; ?>]">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$index'
Loading history...
479
				<?php
480 View Code Duplication
				foreach ( $default as $option => $option_value ) {
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...
481
					$checked = $this->selected( $option_value, $value );
482
					?>
483
					<option value="<?php echo $option; ?>" <?php echo $checked; ?> ><?php echo $option_value; ?></option>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$option'
Loading history...
introduced by
Expected next thing to be a escaping function, not '$checked'
Loading history...
introduced by
Expected next thing to be a escaping function, not '$option_value'
Loading history...
484
					<?php
485
				}
486
				?>
487
				<optgroup label="Donations">
488
					<?php
489 View Code Duplication
					foreach ( $donations as $option => $option_value ) {
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...
490
						$checked = $this->selected( $option_value, $value );
491
						?>
492
						<option value="<?php echo $option; ?>" <?php echo $checked; ?> ><?php echo $option_value; ?></option>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$option'
Loading history...
introduced by
Expected next thing to be a escaping function, not '$checked'
Loading history...
introduced by
Expected next thing to be a escaping function, not '$option_value'
Loading history...
493
						<?php
494
					}
495
					?>
496
				</optgroup>
497
498
				<optgroup label="Donors">
499
					<?php
500 View Code Duplication
					foreach ( $donors as $option => $option_value ) {
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...
501
						$checked = $this->selected( $option_value, $value );
502
						?>
503
						<option value="<?php echo $option; ?>" <?php echo $checked; ?> ><?php echo $option_value; ?></option>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$option'
Loading history...
introduced by
Expected next thing to be a escaping function, not '$checked'
Loading history...
introduced by
Expected next thing to be a escaping function, not '$option_value'
Loading history...
504
						<?php
505
					}
506
					?>
507
				</optgroup>
508
509
				<optgroup label="Forms">
510
					<?php
511 View Code Duplication
					foreach ( $forms as $option => $option_value ) {
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...
512
						$checked = $this->selected( $option_value, $value );
513
						?>
514
						<option value="<?php echo $option; ?>" <?php echo $checked; ?> ><?php echo $option_value; ?></option>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$option'
Loading history...
introduced by
Expected next thing to be a escaping function, not '$checked'
Loading history...
introduced by
Expected next thing to be a escaping function, not '$option_value'
Loading history...
515
						<?php
516
					}
517
					?>
518
				</optgroup>
519
520
				<?php
521
				do_action( 'give_import_dropdown_option', $index, $donations, $donors, $forms, $value );
522
				?>
523
			</select>
524
			<?php
525
		}
526
527
		/**
528
		 * Get column count of csv file.
529
		 *
530
		 * @since 1.8.14
531
		 *
532
		 * @param $file_id
533
		 *
534
		 * @return bool|int
535
		 */
536
		public function get_csv_total( $file_id ) {
537
			$total = false;
538
			if ( $file_id ) {
539
				$file_dir = get_attached_file( $file_id );
540
				if ( $file_dir ) {
541
					$file = new SplFileObject( $file_dir, 'r' );
542
					$file->seek( PHP_INT_MAX );
543
					$total = $file->key() + 1;
544
				}
545
			}
546
547
			return $total;
548
		}
549
550
		/**
551
		 * Get the CSV fields title from the CSV.
552
		 *
553
		 * @since 1.8.14
554
		 *
555
		 * @param (int) $file_id
556
		 * @param int    $index
557
		 * @param string $delimiter
558
		 *
559
		 * @return array|bool $raw_data title of the CSV file fields
560
		 */
561
		public function get_importer( $file_id, $index = 0, $delimiter = ',' ) {
562
			$raw_data = false;
563
			$file_dir = get_attached_file( $file_id );
564
			if ( $file_dir ) {
565
				if ( false !== ( $handle = fopen( $file_dir, 'r' ) ) ) {
566
					$raw_data = fgetcsv( $handle, $index, $delimiter );
567
					// Remove BOM signature from the first item.
568
					if ( isset( $raw_data[0] ) ) {
569
						$raw_data[0] = $this->remove_utf8_bom( $raw_data[0] );
570
					}
571
				}
572
			}
573
574
			return $raw_data;
575
		}
576
577
		/**
578
		 * Remove UTF-8 BOM signature.
579
		 *
580
		 * @since 1.8.14
581
		 *
582
		 * @param  string $string String to handle.
583
		 *
584
		 * @return string
585
		 */
586
		public function remove_utf8_bom( $string ) {
587
			if ( 'efbbbf' === substr( bin2hex( $string ), 0, 6 ) ) {
588
				$string = substr( $string, 3 );
589
			}
590
591
			return $string;
592
		}
593
594
595
		/**
596
		 * Is used to show the process when user upload the donor form.
597
		 *
598
		 * @since 1.8.14
599
		 */
600
		public function render_progress() {
601
			$step = $this->get_step();
602
			?>
603
			<ol class="give-progress-steps">
604
				<li class="<?php echo( 1 === $step ? 'active' : '' ); ?>">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '('
Loading history...
605
					<?php esc_html_e( 'Upload CSV file', 'give' ); ?>
606
				</li>
607
				<li class="<?php echo( 2 === $step ? 'active' : '' ); ?>">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '('
Loading history...
608
					<?php esc_html_e( 'Column mapping', 'give' ); ?>
609
				</li>
610
				<li class="<?php echo( 3 === $step ? 'active' : '' ); ?>">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '('
Loading history...
611
					<?php esc_html_e( 'Import', 'give' ); ?>
612
				</li>
613
				<li class="<?php echo( 4 === $step ? 'active' : '' ); ?>">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '('
Loading history...
614
					<?php esc_html_e( 'Done!', 'give' ); ?>
615
				</li>
616
			</ol>
617
			<?php
618
		}
619
620
		/**
621
		 * Will return the import step.
622
		 *
623
		 * @since 1.8.14
624
		 *
625
		 * @return int $step on which step doest the import is on.
626
		 */
627
		public function get_step() {
628
			$step    = (int) ( isset( $_REQUEST['step'] ) ? give_clean( $_REQUEST['step'] ) : 0 );
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
629
			$on_step = 1;
630
631
			if ( empty( $step ) || 1 === $step ) {
632
				$on_step = 1;
633
			} elseif ( $this->check_for_dropdown_or_import() ) {
634
				$on_step = 3;
635
			} elseif ( 2 === $step ) {
636
				$on_step = 2;
637
			} elseif ( 4 === $step ) {
638
				$on_step = 4;
639
			}
640
641
			return $on_step;
642
		}
643
644
		/**
645
		 * Render donations import page
646
		 *
647
		 * @since 1.8.14
648
		 */
649
		public function render_page() {
650
			include_once GIVE_PLUGIN_DIR . 'includes/admin/tools/views/html-admin-page-import-donations.php';
651
		}
652
653
		/**
654
		 * Add CSV upload HTMl
655
		 *
656
		 * Print the html of the file upload from which CSV will be uploaded.
657
		 *
658
		 * @since 1.8.14
659
		 * @return void
660
		 */
661
		public function render_media_csv() {
662
			?>
663
			<tr valign="top">
664
				<th colspan="2">
665
					<h2 id="give-import-title"><?php esc_html_e( 'Import donations from a CSV file', 'give' ) ?></h2>
666
					<p class="give-field-description"><?php esc_html_e( 'This tool allows you to import or add donation data to your give form(s) via a CSV file.', 'give' ) ?></p>
667
				</th>
668
			</tr>
669
			<?php
670
			$csv         = ( isset( $_POST['csv'] ) ? give_clean( $_POST['csv'] ) : '' );
0 ignored issues
show
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...
671
			$csv_id      = ( isset( $_POST['csv_id'] ) ? give_clean( $_POST['csv_id'] ) : '' );
0 ignored issues
show
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...
672
			$delimiter   = ( isset( $_POST['delimiter'] ) ? give_clean( $_POST['delimiter'] ) : ',' );
0 ignored issues
show
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...
673
			$mode        = ( ! empty( $_POST['mode'] ) ? 'on' : '' );
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
674
			$create_user = ( isset( $_POST['create_user'] ) && isset( $_POST['csv'] ) && 1 === absint( $_POST['create_user'] ) ? 'on' : ( isset( $_POST['csv'] ) ? '' : 'on' ) );
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
675
			$delete_csv  = ( isset( $_POST['delete_csv'] ) && isset( $_POST['csv'] ) && 1 === absint( $_POST['delete_csv'] ) ? 'on' : ( isset( $_POST['csv'] ) ? '' : 'on' ) );
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
676
677
			// Reset csv and csv_id if csv
678
			if ( empty( $csv_id ) || ! $this->is_valid_csv( $csv_id, $csv ) ) {
0 ignored issues
show
Documentation introduced by
$csv_id is of type string|array, but the function expects a integer|boolean.

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...
Bug introduced by
It seems like $csv defined by isset($_POST['csv']) ? g...ean($_POST['csv']) : '' on line 670 can also be of type array; however, Give_Import_Donations::is_valid_csv() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
679
				$csv_id = $csv = '';
680
			}
681
682
			$settings = array(
683
				array(
684
					'id'          => 'csv',
685
					'name'        => __( 'Choose a CSV file:', 'give' ),
686
					'type'        => 'file',
687
					'attributes'  => array( 'editing' => 'false', 'library' => 'text' ),
688
					'description' => __( 'The file must be a Comma Seperated Version (CSV) file type only.', 'give' ),
689
					'fvalue'      => 'url',
690
					'default'     => $csv,
691
				),
692
				array(
693
					'id'    => 'csv_id',
694
					'type'  => 'hidden',
695
					'value' => $csv_id,
696
				),
697
				array(
698
					'id'          => 'delimiter',
699
					'name'        => __( 'CSV Delimiter:', 'give' ),
700
					'type'        => 'text',
701
					'description' => __( 'In case your CSV file supports a different type of separator (or delimiter) -- like a tab or space -- you can set that here.', 'give' ),
702
					'attributes'  => array( 'placeholder' => ',', 'size' => '2' ),
703
					'default'     => $delimiter,
704
				),
705
				array(
706
					'id'          => 'mode',
707
					'name'        => __( 'Test Mode:', 'give' ),
708
					'type'        => 'checkbox',
709
					'description' => __( 'Test mode allows you to preview what this import would look like without making any actual changes to your site or your database.', 'give' ),
710
					'default'     => $mode,
711
				),
712
				array(
713
					'id'          => 'create_user',
714
					'name'        => __( 'Create WP users for new donors:', 'give' ),
715
					'type'        => 'checkbox',
716
					'description' => __( 'The importer can create WordPress user accounts based on the names and email addresses of the donations in your CSV file. Enable this option if you\'d like the importer to do that.', 'give' ),
717
					'default'     => $create_user,
718
				),
719
				array(
720
					'id'          => 'delete_csv',
721
					'name'        => __( 'Delete CSV after import:', 'give' ),
722
					'type'        => 'checkbox',
723
					'description' => __( 'Your CSV file will be uploaded via the WordPress Media Library. It\'s a good idea to delete it after the import is finished so that your sensitive data is not accessible on the web. Disable this only if you plan to delete the file manually later.', 'give' ),
724
					'default'     => $delete_csv,
725
				),
726
			);
727
728
			$settings = apply_filters( 'give_import_file_upload_html', $settings );
729
730
			Give_Admin_Settings::output_fields( $settings, 'give_settings' );
731
		}
732
733
		/**
734
		 * Run when user click on the submit button.
735
		 *
736
		 * @since 1.8.14
737
		 */
738
		public function save() {
739
			// Get the current step.
740
			$step = $this->get_step();
741
742
			// Validation for first step.
743
			if ( 1 === $step ) {
744
				$csv_id = absint( $_POST['csv_id'] );
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-validated input variable: $_POST
Loading history...
745
746
				if ( $this->is_valid_csv( $csv_id, esc_url( $_POST['csv'] ) ) ) {
747
748
					$url = give_import_page_url( (array) apply_filters( 'give_import_step_two_url', array(
749
						'step'          => '2',
750
						'importer-type' => $this->importer_type,
751
						'csv'           => $csv_id,
752
						'delimiter'     => isset( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : ',',
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
753
						'mode'          => isset( $_REQUEST['mode'] ) ? give_clean( $_REQUEST['mode'] ) : '0',
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
754
						'create_user'   => isset( $_REQUEST['create_user'] ) ? give_clean( $_REQUEST['create_user'] ) : '0',
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
755
						'delete_csv'    => isset( $_REQUEST['delete_csv'] ) ? give_clean( $_REQUEST['delete_csv'] ) : '0',
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
756
					) ) );
757
					?>
758
					<script type="text/javascript">
759
						window.location = "<?php echo $url; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$url'
Loading history...
760
					</script>
761
					<?php
762
				}
763
			}
764
		}
765
766
		/**
767
		 * Check if user uploaded csv is valid or not.
768
		 *
769
		 * @since  1.8.14
770
		 * @access public
771
		 *
772
		 * @param int|bool $csv       ID of the CSV files.
773
		 * @param string   $match_url ID of the CSV files.
774
		 *
775
		 * @return bool $has_error CSV is valid or not.
776
		 */
777
		private function is_valid_csv( $csv = false, $match_url = '' ) {
778
			$is_valid_csv = true;
779
780
			if ( $csv ) {
781
				$csv_url = wp_get_attachment_url( $csv );
782
783
				if (
784
					! $csv_url ||
785
					( ! empty( $match_url ) && ( $csv_url !== $match_url ) ) ||
786
					( ( $mime_type = get_post_mime_type( $csv ) ) && ! strpos( $mime_type, 'csv' ) )
787
				) {
788
					$is_valid_csv = false;
789
					Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid CSV file.', 'give' ) );
790
				}
791
			} else {
792
				$is_valid_csv = false;
793
				Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid CSV file.', 'give' ) );
794
			}
795
796
			return $is_valid_csv;
797
		}
798
799
800
		/**
801
		 * Render report import field
802
		 *
803
		 * @since  1.8.14
804
		 * @access public
805
		 *
806
		 * @param $field
807
		 * @param $option_value
808
		 */
809
		public function render_import_field( $field, $option_value ) {
810
			include_once GIVE_PLUGIN_DIR . 'includes/admin/tools/views/html-admin-page-imports.php';
811
		}
812
813
		/**
814
		 * Get if current page import donations page or not
815
		 *
816
		 * @since 1.8.14
817
		 * @return bool
818
		 */
819
		private function is_donations_import_page() {
820
			return 'import' === give_get_current_setting_tab() &&
821
			       isset( $_GET['importer-type'] ) &&
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
822
			       $this->importer_type === give_clean( $_GET['importer-type'] );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
823
		}
824
	}
825
826
	Give_Import_Donations::get_instance()->setup();
827
}
828