Test Failed
Push — master ( 25adfe...70178c )
by Devin
01:46
created

Give_Import_Donations::html()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 46
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 28
nc 10
nop 0
dl 0
loc 46
rs 8.4751
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
		 * Update notice
124
		 *
125
		 * @since 1.8.14
126
		 *
127
		 * @param $messages
128
		 *
129
		 * @return mixed
130
		 */
131
		public function update_notices( $messages ) {
132
			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...
133
				unset( $messages['give-setting-updated'] );
134
			}
135
136
			return $messages;
137
		}
138
139
		/**
140
		 * Print submit and nonce button.
141
		 *
142
		 * @since 1.8.14
143
		 */
144
		public function submit() {
145
			wp_nonce_field( 'give-save-settings', '_give-save-settings' );
146
			?>
147
			<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...
148
			<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...
149
			<?php
150
		}
151
152
		/**
153
		 * Print the HTML for importer.
154
		 *
155
		 * @since 1.8.14
156
		 */
157
		public function html() {
158
			$step = $this->get_step();
159
160
			// Show progress.
161
			$this->render_progress();
162
			?>
163
			<section>
164
				<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...
165
					<tbody>
166
						<?php
167
						switch ( $this->get_step() ) {
168
							case 1:
169
								$this->render_media_csv();
170
								break;
171
172
							case 2:
173
								$this->render_dropdown();
174
								break;
175
176
							case 3:
177
								$this->start_import();
178
								break;
179
180
							case 4:
181
								$this->import_success();
182
						}
183
184
						if ( false === $this->check_for_dropdown_or_import() ) {
185
							?>
186
							<tr valign="top">
187
								<th></th>
188
								<th>
189
									<input type="submit"
190
										   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...
191
										   id="recount-stats-submit"
192
										   value="<?php esc_attr_e( 'Submit', 'give' ); ?>"/>
193
								</th>
194
							</tr>
195
							<?php
196
						}
197
						?>
198
					</tbody>
199
				</table>
200
			</section>
201
			<?php
202
		}
203
204
		/**
205
		 * Show success notice
206
		 *
207
		 * @since 1.8.14
208
		 */
209
		public function import_success() {
210
211
			$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...
212
			$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...
213
			if ( ! empty( $delete_csv ) && ! empty( $csv ) ) {
214
				wp_delete_attachment( $csv, true );
215
			}
216
217
			$report      = give_import_donation_report();
218
			$report_html = array(
219
				'duplicate_donor'    => array(
220
					__( '%s duplicate %s detected', 'give' ),
221
					__( 'donor', 'give' ),
222
					__( 'donors', 'give' ),
223
				),
224
				'create_donor'       => array(
225
					__( '%s %s created', 'give' ),
226
					__( 'donor', 'give' ),
227
					__( 'donors', 'give' ),
228
				),
229
				'create_form'        => array(
230
					__( '%s donation %s created', 'give' ),
231
					__( 'form', 'give' ),
232
					__( 'forms', 'give' ),
233
				),
234
				'duplicate_donation' => array(
235
					__( '%s duplicate %s detected', 'give' ),
236
					__( 'donation', 'give' ),
237
					__( 'donations', 'give' ),
238
				),
239
				'create_donation'    => array(
240
					__( '%s %s imported', 'give' ),
241
					__( 'donation', 'give' ),
242
					__( 'donations', 'give' ),
243
				),
244
			);
245
			$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...
246
			-- $total;
247
			$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...
248
			?>
249
			<tr valign="top" class="give-import-dropdown">
250
				<th colspan="2">
251
					<h2>
252
						<?php
253
						if ( $success ) {
254
							echo sprintf(
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'sprintf'
Loading history...
255
								__( 'Import complete! %s donations processed', 'give' ),
256
								"<strong>{$total}</strong>"
257
							);
258
						} else {
259
							echo sprintf(
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'sprintf'
Loading history...
260
								__( 'Failed to import %s donations', 'give' ),
261
								"<strong>{$total}</strong>"
262
							);
263
						}
264
						?>
265
					</h2>
266
267
					<?php
268
					$text      = __( 'Import Donation', 'give' );
269
					$query_arg = array(
270
						'post_type' => 'give_forms',
271
						'page'      => 'give-tools',
272
						'tab'       => 'import',
273
					);
274
					if ( $success ) {
275
						$query_arg = array(
276
							'post_type' => 'give_forms',
277
							'page'      => 'give-payment-history',
278
						);
279
						$text      = __( 'View Donations', 'give' );
280
					}
281
282
					foreach ( $report as $key => $value ) {
283
						if ( array_key_exists( $key, $report_html ) && ! empty( $value ) ) {
284
							?>
285
							<p>
286
								<?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...
287
							</p>
288
							<?php
289
						}
290
					}
291
					?>
292
293
					<p>
294
						<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...
295
					</p>
296
				</th>
297
			</tr>
298
			<?php
299
		}
300
301
		/**
302
		 * Will start Import
303
		 *
304
		 * @since 1.8.14
305
		 */
306
		public function start_import() {
307
			// Reset the donation form report.
308
			give_import_donation_report_reset();
309
310
			$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...
311
			$delimiter   = ( ! empty( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : '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-sanitized 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 $delimiter; ?>" name="delimiter">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$delimiter'
Loading history...
358
					<input type="hidden" value='<?php echo maybe_serialize( self::get_importer( $csv, 0, $delimiter ) ); ?>'
0 ignored issues
show
Bug introduced by
It seems like $delimiter defined by !empty($_REQUEST['delimi...T['delimiter']) : 'csv' on line 311 can also be of type array; however, Give_Import_Donations::get_importer() 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...
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
			$delimiter = ( ! empty( $_GET['delimiter'] ) ? give_clean( $_GET['delimiter'] ) : '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-sanitized input variable: $_GET
Loading history...
410
411
			// TO check if the CSV files that is being add is valid or not if not then redirect to first step again
412
			if ( ! $this->is_valid_csv( $csv ) ) {
413
				$url = give_import_page_url();
414
				?>
415
				<script type="text/javascript">
416
					window.location = "<?php echo $url; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$url'
Loading history...
417
				</script>
418
				<?php
419
			} else {
420
				?>
421
				<tr valign="top" class="give-import-dropdown">
422
					<th colspan="2">
423
						<h2 id="give-import-title"><?php esc_html_e( 'Map CSV fields to donations', 'give' ) ?></h2>
424
						<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>
425
					</th>
426
				</tr>
427
428
				<tr valign="top" class="give-import-dropdown">
429
					<th><b><?php esc_html_e( 'Column name', 'give' ); ?></b></th>
430
					<th><b><?php esc_html_e( 'Map to field', 'give' ); ?></b></th>
431
				</tr>
432
433
				<?php
434
				$raw_key   = $this->get_importer( $csv, 0, $delimiter );
0 ignored issues
show
Bug introduced by
It seems like $delimiter defined by !empty($_GET['delimiter'...T['delimiter']) : 'csv' on line 409 can also be of type array; however, Give_Import_Donations::get_importer() 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...
435
				$donations = give_import_donations_options();
436
				$donors    = give_import_donor_options();
437
				$forms     = give_import_donation_form_options();
438
				$mapto     = (array) ( isset( $_REQUEST['mapto'] ) ? $_REQUEST['mapto'] : array() );
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...
439
440
				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...
441
					?>
442
					<tr valign="top" class="give-import-option">
443
						<th><?php echo $value; ?></th>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$value'
Loading history...
444
						<th>
445
							<?php
446
							$this->get_columns( $index, $donations, $donors, $forms, $value, $mapto );
447
							?>
448
						</th>
449
					</tr>
450
					<?php
451
				}
452
			}
453
		}
454
455
		/**
456
		 * @param $option_value
457
		 * @param $value
458
		 *
459
		 * @return string
460
		 */
461
		public function selected( $option_value, $value ) {
462
			$selected = '';
463
			if ( stristr( $value, $option_value ) ) {
464
				$selected = 'selected';
465
			} elseif ( strrpos( $value, '_' ) && stristr( $option_value, 'Import as Meta' ) ) {
466
				$selected = 'selected';
467
			}
468
469
			return $selected;
470
		}
471
472
		/**
473
		 * Print the columns from the CSV.
474
		 *
475
		 * @since 1.8.14
476
		 */
477
		public function get_columns( $index, $donations, $donors, $forms, $value = false, $mapto = array() ) {
478
			$default       = give_import_default_options();
479
			$current_mapto = (string) ( ! empty( $mapto[ $index ] ) ? $mapto[ $index ] : '' );
480
			?>
481
			<select name="mapto[<?php echo $index; ?>]">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$index'
Loading history...
482
				<?php
483 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...
484
					$checked = ( ( $current_mapto === $option ) ? 'selected' : false );
485
					if ( empty( $checked ) ) {
486
						$checked = $this->selected( $option_value, $value );
487
					}
488
					?>
489
					<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...
490
					<?php
491
				}
492
				?>
493
				<optgroup label="Donations">
494
					<?php
495 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...
496
						$checked = ( ( $current_mapto === $option ) ? 'selected' : false );
497
						if ( empty( $checked ) ) {
498
							$checked = $this->selected( $option_value, $value );
499
						}
500
						?>
501
						<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...
502
						<?php
503
					}
504
					?>
505
				</optgroup>
506
507
				<optgroup label="Donors">
508
					<?php
509 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...
510
						$checked = ( ( $current_mapto === $option ) ? 'selected' : false );
511
						if ( empty( $checked ) ) {
512
							$checked = $this->selected( $option_value, $value );
513
						}
514
						?>
515
						<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...
516
						<?php
517
					}
518
					?>
519
				</optgroup>
520
521
				<optgroup label="Forms">
522
					<?php
523 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...
524
						$checked = ( ( $current_mapto === $option ) ? 'selected' : false );
525
						if ( empty( $checked ) ) {
526
							$checked = $this->selected( $option_value, $value );
527
						}
528
						?>
529
						<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...
530
						<?php
531
					}
532
					?>
533
				</optgroup>
534
535
				<?php
536
				do_action( 'give_import_dropdown_option', $index, $donations, $donors, $forms, $value );
537
				?>
538
			</select>
539
			<?php
540
		}
541
542
		/**
543
		 * Get column count of csv file.
544
		 *
545
		 * @since 1.8.14
546
		 *
547
		 * @param $file_id
548
		 *
549
		 * @return bool|int
550
		 */
551
		public function get_csv_total( $file_id ) {
552
			$total = false;
553
			if ( $file_id ) {
554
				$file_dir = get_attached_file( $file_id );
555
				if ( $file_dir ) {
556
					$file = new SplFileObject( $file_dir, 'r' );
557
					$file->seek( PHP_INT_MAX );
558
					$total = $file->key() + 1;
559
				}
560
			}
561
562
			return $total;
563
		}
564
565
		/**
566
		 * Get the CSV fields title from the CSV.
567
		 *
568
		 * @since 1.8.14
569
		 *
570
		 * @param (int) $file_id
571
		 * @param int    $index
572
		 * @param string $delimiter
573
		 *
574
		 * @return array|bool $raw_data title of the CSV file fields
575
		 */
576
		public function get_importer( $file_id, $index = 0, $delimiter = 'csv' ) {
577
			/**
578
			 * Filter to modify delimiter of Import.
579
			 *
580
			 * @since 1.8.15
581
			 *
582
			 * Return string $delimiter.
583
			 */
584
			$delimiter = (string) apply_filters( 'give_import_delimiter_set', $delimiter );
585
586
			$raw_data = false;
587
			$file_dir = get_attached_file( $file_id );
588
			if ( $file_dir ) {
589
				if ( false !== ( $handle = fopen( $file_dir, 'r' ) ) ) {
590
					$raw_data = fgetcsv( $handle, $index, $delimiter );
591
					// Remove BOM signature from the first item.
592
					if ( isset( $raw_data[0] ) ) {
593
						$raw_data[0] = $this->remove_utf8_bom( $raw_data[0] );
594
					}
595
				}
596
			}
597
598
			return $raw_data;
599
		}
600
601
		/**
602
		 * Remove UTF-8 BOM signature.
603
		 *
604
		 * @since 1.8.14
605
		 *
606
		 * @param  string $string String to handle.
607
		 *
608
		 * @return string
609
		 */
610
		public function remove_utf8_bom( $string ) {
611
			if ( 'efbbbf' === substr( bin2hex( $string ), 0, 6 ) ) {
612
				$string = substr( $string, 3 );
613
			}
614
615
			return $string;
616
		}
617
618
619
		/**
620
		 * Is used to show the process when user upload the donor form.
621
		 *
622
		 * @since 1.8.14
623
		 */
624
		public function render_progress() {
625
			$step = $this->get_step();
626
			?>
627
			<ol class="give-progress-steps">
628
				<li class="<?php echo( 1 === $step ? 'active' : '' ); ?>">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '('
Loading history...
629
					<?php esc_html_e( 'Upload CSV file', 'give' ); ?>
630
				</li>
631
				<li class="<?php echo( 2 === $step ? 'active' : '' ); ?>">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '('
Loading history...
632
					<?php esc_html_e( 'Column mapping', 'give' ); ?>
633
				</li>
634
				<li class="<?php echo( 3 === $step ? 'active' : '' ); ?>">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '('
Loading history...
635
					<?php esc_html_e( 'Import', 'give' ); ?>
636
				</li>
637
				<li class="<?php echo( 4 === $step ? 'active' : '' ); ?>">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '('
Loading history...
638
					<?php esc_html_e( 'Done!', 'give' ); ?>
639
				</li>
640
			</ol>
641
			<?php
642
		}
643
644
		/**
645
		 * Will return the import step.
646
		 *
647
		 * @since 1.8.14
648
		 *
649
		 * @return int $step on which step doest the import is on.
650
		 */
651
		public function get_step() {
652
			$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...
653
			$on_step = 1;
654
655
			if ( empty( $step ) || 1 === $step ) {
656
				$on_step = 1;
657
			} elseif ( $this->check_for_dropdown_or_import() ) {
658
				$on_step = 3;
659
			} elseif ( 2 === $step ) {
660
				$on_step = 2;
661
			} elseif ( 4 === $step ) {
662
				$on_step = 4;
663
			}
664
665
			return $on_step;
666
		}
667
668
		/**
669
		 * Render donations import page
670
		 *
671
		 * @since 1.8.14
672
		 */
673
		public function render_page() {
674
			include_once GIVE_PLUGIN_DIR . 'includes/admin/tools/views/html-admin-page-import-donations.php';
675
		}
676
677
		/**
678
		 * Add CSV upload HTMl
679
		 *
680
		 * Print the html of the file upload from which CSV will be uploaded.
681
		 *
682
		 * @since 1.8.14
683
		 * @return void
684
		 */
685
		public function render_media_csv() {
686
			?>
687
			<tr valign="top">
688
				<th colspan="2">
689
					<h2 id="give-import-title"><?php esc_html_e( 'Import donations from a CSV file', 'give' ) ?></h2>
690
					<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>
691
				</th>
692
			</tr>
693
			<?php
694
			$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...
695
			$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...
696
			$delimiter   = ( isset( $_POST['delimiter'] ) ? give_clean( $_POST['delimiter'] ) : '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...
697
			$mode        = empty( $_POST['mode'] ) ?
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
698
				'disabled' :
699
				( give_is_setting_enabled( give_clean( $_POST['mode'] ) ) ? 'enabled' : 'disabled' );
0 ignored issues
show
Bug introduced by
It seems like give_clean($_POST['mode']) targeting give_clean() can also be of type array; however, give_is_setting_enabled() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

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...
700
			$create_user = empty( $_POST['create_user'] ) ?
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
701
				'enabled' :
702
				( give_is_setting_enabled( give_clean( $_POST['create_user'] ) ) ? 'enabled' : 'disabled' );
0 ignored issues
show
Bug introduced by
It seems like give_clean($_POST['create_user']) targeting give_clean() can also be of type array; however, give_is_setting_enabled() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

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...
703
			$delete_csv  = empty( $_POST['delete_csv'] ) ?
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
704
				'enabled' :
705
				( give_is_setting_enabled( give_clean( $_POST['delete_csv'] ) ) ? 'enabled' : 'disabled' );
0 ignored issues
show
Bug introduced by
It seems like give_clean($_POST['delete_csv']) targeting give_clean() can also be of type array; however, give_is_setting_enabled() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

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...
706
707
			// Reset csv and csv_id if csv
708
			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 694 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...
709
				$csv_id = $csv = '';
710
			}
711
712
			$settings = array(
713
				array(
714
					'id'          => 'csv',
715
					'name'        => __( 'Choose a CSV file:', 'give' ),
716
					'type'        => 'file',
717
					'attributes'  => array( 'editing' => 'false', 'library' => 'text' ),
718
					'description' => __( 'The file must be a Comma Seperated Version (CSV) file type only.', 'give' ),
719
					'fvalue'      => 'url',
720
					'default'     => $csv,
721
				),
722
				array(
723
					'id'    => 'csv_id',
724
					'type'  => 'hidden',
725
					'value' => $csv_id,
726
				),
727
				array(
728
					'id'          => 'delimiter',
729
					'name'        => __( 'CSV Delimiter:', 'give' ),
730
					'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' ),
731
					'default'     => $delimiter,
732
					'type'        => 'select',
733
					'options'     => array(
734
						'csv'                  => esc_html__( 'Comma', 'give' ),
735
						'tab-separated-values' => esc_html__( 'Tab', 'give' ),
736
					),
737
				),
738
				array(
739
					'id'          => 'mode',
740
					'name'        => __( 'Test Mode:', 'give' ),
741
					'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' ),
742
					'default'     => $mode,
743
					'type'        => 'radio_inline',
744
					'options'     => array(
745
						'enabled'  => __( 'Enabled', 'give' ),
746
						'disabled' => __( 'Disabled', 'give' ),
747
					),
748
				),
749
				array(
750
					'id'          => 'create_user',
751
					'name'        => __( 'Create WP users for new donors:', 'give' ),
752
					'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' ),
753
					'default'     => $create_user,
754
					'type'        => 'radio_inline',
755
					'options'     => array(
756
						'enabled'  => __( 'Enabled', 'give' ),
757
						'disabled' => __( 'Disabled', 'give' ),
758
					),
759
				),
760
				array(
761
					'id'          => 'delete_csv',
762
					'name'        => __( 'Delete CSV after import:', 'give' ),
763
					'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' ),
764
					'default'     => $delete_csv,
765
					'type'        => 'radio_inline',
766
					'options'     => array(
767
						'enabled'  => __( 'Enabled', 'give' ),
768
						'disabled' => __( 'Disabled', 'give' ),
769
					),
770
				),
771
			);
772
773
			$settings = apply_filters( 'give_import_file_upload_html', $settings );
774
775
			Give_Admin_Settings::output_fields( $settings, 'give_settings' );
776
		}
777
778
		/**
779
		 * Run when user click on the submit button.
780
		 *
781
		 * @since 1.8.14
782
		 */
783
		public function save() {
784
			// Get the current step.
785
			$step = $this->get_step();
786
787
			// Validation for first step.
788
			if ( 1 === $step ) {
789
				$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...
790
791
				if ( $this->is_valid_csv( $csv_id, esc_url( $_POST['csv'] ) ) ) {
792
793
					$url = give_import_page_url( (array) apply_filters( 'give_import_step_two_url', array(
794
						'step'          => '2',
795
						'importer-type' => $this->importer_type,
796
						'csv'           => $csv_id,
797
						'delimiter'     => isset( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : '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-sanitized input variable: $_REQUEST
Loading history...
798
						'mode'          => empty( $_POST['mode'] ) ?
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
799
							'0' :
800
							( give_is_setting_enabled( give_clean( $_POST['mode'] ) ) ? '1' : '0' ),
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...
801
						'create_user'   => empty( $_POST['create_user'] ) ?
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
802
							'0' :
803
							( give_is_setting_enabled( give_clean( $_POST['create_user'] ) ) ? '1' : '0' ),
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...
804
						'delete_csv'    => empty( $_POST['delete_csv'] ) ?
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
805
							'1' :
806
							( give_is_setting_enabled( give_clean( $_POST['delete_csv'] ) ) ? '1' : '0' ),
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...
807
					) ) );
808
					?>
809
					<script type="text/javascript">
810
						window.location = "<?php echo $url; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$url'
Loading history...
811
					</script>
812
					<?php
813
				}
814
			}
815
		}
816
817
		/**
818
		 * Check if user uploaded csv is valid or not.
819
		 *
820
		 * @since  1.8.14
821
		 * @access public
822
		 *
823
		 * @param int|bool $csv       ID of the CSV files.
824
		 * @param string   $match_url ID of the CSV files.
825
		 *
826
		 * @return bool $has_error CSV is valid or not.
827
		 */
828
		private function is_valid_csv( $csv = false, $match_url = '' ) {
829
			$is_valid_csv = true;
830
831
			if ( $csv ) {
832
				$csv_url = wp_get_attachment_url( $csv );
833
834
				$delimiter = ( ! empty( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : '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-sanitized input variable: $_REQUEST
Loading history...
835
836
				if (
837
					! $csv_url ||
838
					( ! empty( $match_url ) && ( $csv_url !== $match_url ) ) ||
839
					( ( $mime_type = get_post_mime_type( $csv ) ) && ! strpos( $mime_type, $delimiter ) )
840
				) {
841
					$is_valid_csv = false;
842
					Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid CSV file.', 'give' ) );
843
				}
844
			} else {
845
				$is_valid_csv = false;
846
				Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid CSV file.', 'give' ) );
847
			}
848
849
			return $is_valid_csv;
850
		}
851
852
853
		/**
854
		 * Render report import field
855
		 *
856
		 * @since  1.8.14
857
		 * @access public
858
		 *
859
		 * @param $field
860
		 * @param $option_value
861
		 */
862
		public function render_import_field( $field, $option_value ) {
863
			include_once GIVE_PLUGIN_DIR . 'includes/admin/tools/views/html-admin-page-imports.php';
864
		}
865
866
		/**
867
		 * Get if current page import donations page or not
868
		 *
869
		 * @since 1.8.14
870
		 * @return bool
871
		 */
872
		private function is_donations_import_page() {
873
			return 'import' === give_get_current_setting_tab() &&
874
			       isset( $_GET['importer-type'] ) &&
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
875
			       $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...
876
		}
877
	}
878
879
	Give_Import_Donations::get_instance()->setup();
880
}
881