Test Failed
Pull Request — master (#2054)
by Devin
05:04
created

Give_Settings_Import::render_media_csv()   F

Complexity

Conditions 12
Paths 1152

Size

Total Lines 55
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 42
nc 1152
nop 0
dl 0
loc 55
rs 3.4396
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Give Settings Page/Tab
4
 *
5
 * @package     Give
6
 * @subpackage  Classes/Give_Settings_Import
7
 * @copyright   Copyright (c) 2016, WordImpress
8
 * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
 * @since       1.8
10
 */
11
12
if ( ! defined( 'ABSPATH' ) ) {
13
	exit; // Exit if accessed directly
14
}
15
16
if ( ! class_exists( 'Give_Settings_Import' ) ) {
17
18
	/**
19
	 * Give_Settings_Import.
20
	 *
21
	 * Add a submenu page in give tools menu called Import donations which import the donations from the CSV files.
22
	 *
23
	 * @since 1.8.13
24
	 */
25
	class Give_Settings_Import extends Give_Settings_Page {
26
27
		/**
28
		 * Setting page id.
29
		 *
30
		 * @since 1.8.13
31
		 *
32
		 * @var   string
33
		 */
34
		protected $id = '';
35
36
		/**
37
		 * Setting page label.
38
		 *
39
		 * @since 1.8.13
40
		 *
41
		 * @var   string
42
		 */
43
		protected $label = '';
44
45
		/**
46
		 * Importing donation per page.
47
		 *
48
		 * @since 1.8.13
49
		 *
50
		 * @var   int
51
		 */
52
		public static $per_page = 5;
53
54
		/**
55
		 * Constructor.
56
		 */
57
		public function __construct() {
58
			$this->id    = 'import';
59
			$this->label = __( 'Import Donations', 'give' );
60
61
			// Add Import tab in submenu.
62
			add_filter( 'give-tools_tabs_array', array( $this, 'add_settings_page' ), 20 );
63
			// Will display html of the import donation.
64
			add_action( 'give_admin_field_tools_import', array( $this, 'render_import_field' ), 10, 2 );
65
			// Will call the function that genetrated the hook called 'give_admin_field_tools_import'.
66
			add_action( "give-tools_settings_{$this->id}_page", array( $this, 'output' ) );
67
			// Do not use main form for this tab.
68
			if ( give_get_current_setting_tab() === $this->id ) {
69
				add_action( "give-tools_open_form", '__return_empty_string' );
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal give-tools_open_form does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
70
				add_action( "give-tools_close_form", '__return_empty_string' );
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal give-tools_close_form does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
71
			}
72
			// Run when form submit.
73
			add_action( 'give-tools_save_import', array( $this, 'save' ) );
74
			add_action( 'give-tools_update_notices', array( $this, 'update_notices' ), 11, 1 );
75
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
76
77
			// Will add the progress of the import
78
			add_action( 'give_tools_import_form_before_start', array( 'Give_Settings_Import', 'progress' ), 10 );
79
			// Print the HTML.
80
			add_action( 'give_tools_import_form_start', array( 'Give_Settings_Import', 'html' ), 10 );
81
			// Used to add submit button.
82
			add_action( 'give_tools_import_form_end', array( 'Give_Settings_Import', 'submit' ), 10 );
83
			// Print the html for CSV file upload.
84
			add_action( 'give_admin_field_media_csv', array( $this, 'render_media_csv' ), 10, 2 );
85
		}
86
87
		static function update_notices( $messages ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
88
			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...
89
				unset( $messages['give-setting-updated'] );
90
			}
91
92
			return $messages;
93
		}
94
95
		/**
96
		 * Print submit and nonce button.
97
		 *
98
		 * @since 1.8.13
99
		 */
100
		static function submit() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
101
			wp_nonce_field( 'give-save-settings', '_give-save-settings' );
102
			?>
103
			<input type="hidden" class="import-step" id="import-step" name="step"
104
			       value="<?php echo Give_Settings_Import::get_step(); ?>"/>
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'Give_Settings_Import'
Loading history...
105
			<?php
106
		}
107
108
		/**
109
		 * Print the HTML for importer.
110
		 *
111
		 * @since 1.8.13
112
		 */
113
		static function html() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
114
			$step = Give_Settings_Import::get_step();
115
			?>
116
			<section>
117
				<table class="widefat export-options-table give-table <?php echo 'step-' . $step; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$step'
Loading history...
118
				       id="<?php echo 'step-' . $step; ?>">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$step'
Loading history...
119
					<tbody>
120
					<?php
121
					if ( 1 === $step ) {
122
						// Get the html of CSV file upload.
123
						Give_Settings_Import::render_media_csv();
124
					} elseif ( 2 === $step ) {
125
						Give_Settings_Import::render_dropdown();
126
					} elseif ( 3 === $step ) {
127
						// Drop down for importer files.
128
						Give_Settings_Import::start_import();
129
					} elseif ( 4 === $step ) {
130
						// Successful or fail message.
131
						Give_Settings_Import::import_success();
132
					}
133
134
					if ( self::check_for_dropdown_or_import() == false ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
introduced by
Found "== false". Use Yoda Condition checks, you must
Loading history...
135
						$step = Give_Settings_Import::get_step();
136
						?>
137
						<tr valign="top">
138
							<th></th>
139
							<th>
140
								<input type="submit"
141
								       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'
Loading history...
142
								       id="recount-stats-submit"
143
								       value="<?php esc_attr_e( 'Submit', 'give' ); ?>"/>
144
							</th>
145
						</tr>
146
						<?php
147
					}
148
					?>
149
					</tbody>
150
				</table>
151
			</section>
152
			<?php
153
		}
154
155
		static function import_success() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
156
157
			$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...
158
			$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...
159
			if ( ! empty( $delete_csv ) && ! empty( $csv ) ) {
160
				wp_delete_attachment( $csv, true );
161
			}
162
163
			$report      = give_import_donation_report();
164
			$report_html = array(
165
				'duplicate_donor'    => array(
166
					__( '%s duplicate %s detected', 'give' ),
167
					__( 'donor', 'give' ),
168
					__( 'donors', 'give' ),
169
				),
170
				'create_donor'       => array(
171
					__( '%s %s created', 'give' ),
172
					__( 'donor', 'give' ),
173
					__( 'donors', 'give' ),
174
				),
175
				'create_form'        => array(
176
					__( '%s donation %s created', 'give' ),
177
					__( 'form', 'give' ),
178
					__( 'forms', 'give' ),
179
				),
180
				'duplicate_donation' => array(
181
					__( '%s duplicate %s detected', 'give' ),
182
					__( 'donation', 'give' ),
183
					__( 'donations', 'give' ),
184
				),
185
				'create_donation'    => array(
186
					__( '%s %s imported', 'give' ),
187
					__( 'donation', 'give' ),
188
					__( 'donations', 'give' ),
189
				),
190
			);
191
			$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...
192
			$total       = $total - 1;
193
			$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...
194
			?>
195
			<tr valign="top" class="give-import-dropdown">
196
				<th colspan="2">
197
					<h2>
198
						<?php
199
						if ( $success ) {
200
							echo sprintf( __( 'Import complete! %s donations processed', 'give' ), "<strong>{$total}</strong>" );
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'sprintf'
Loading history...
201
						} else {
202
							echo sprintf( __( 'Failed to import %s donations', 'give' ), "<strong>{$total}</strong>" );
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'sprintf'
Loading history...
203
						}
204
						?>
205
					</h2>
206
207
					<?php
208
					$text      = __( 'Import Donation', 'give' );
209
					$query_arg = array(
210
						'post_type' => 'give_forms',
211
						'page'      => 'give-tools',
212
						'tab'       => 'import',
213
					);
214
					if ( $success ) {
215
						$query_arg = array(
216
							'post_type' => 'give_forms',
217
							'page'      => 'give-payment-history',
218
						);
219
						$text      = __( 'View Donations', 'give' );
220
					}
221
222
					foreach ( $report as $key => $value ) {
223
						if ( array_key_exists( $key, $report_html ) && ! empty( $value ) ) {
224
							?>
225
							<p>
226
								<?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...
227
							</p>
228
							<?php
229
						}
230
					}
231
					?>
232
233
					<p>
234
						<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...
235
					</p>
236
				</th>
237
			</tr>
238
			<?php
239
		}
240
241
		/**
242
		 * Will start Import
243
		 */
244
		static function start_import() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
245
			// Reset the donation form report.
246
			give_import_donation_report_reset();
247
248
			$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...
249
			$index_start = 1;
250
			$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...
251
			$next        = true;
252
			$total       = self::get_csv_total( $csv );
253
			if ( self::$per_page < $total ) {
254
				$total_ajax = ceil( $total / self::$per_page );
255
				$index_end  = self::$per_page;
256
			} else {
257
				$total_ajax = 1;
258
				$index_end  = $total;
259
				$next       = false;
260
			}
261
			$current_percentage = 100 / ( $total_ajax + 1 );
262
263
			?>
264
			<tr valign="top" class="give-import-dropdown">
265
				<th colspan="2">
266
					<h2 id="give-import-title"><?php esc_html_e( 'Importing', 'give' ) ?></h2>
267
					<p class="give-field-description"><?php esc_html_e( 'Your donations are now being imported...', 'give' ) ?></p>
268
				</th>
269
			</tr>
270
271
			<tr valign="top" class="give-import-dropdown">
272
				<th colspan="2">
273
					<span class="spinner is-active"></span>
274
					<div class="give-progress"
275
					     data-current="1"
276
					     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...
277
					     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...
278
					     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...
279
					     data-next="<?php echo $next; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$next'
Loading history...
280
					     data-total="<?php echo $total; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$total'
Loading history...
281
					     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...
282
283
						<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...
284
					</div>
285
					<input type="hidden" value="3" name="step">
286
					<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...
287
					       class="mapto">
288
					<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...
289
					<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...
290
					<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...
291
					       class="create_user">
292
					<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...
293
					       class="delete_csv">
294
					<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...
295
					<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...
296
					       name="main_key"
297
					       class="main_key">
298
				</th>
299
			</tr>
300
301
			<script type="text/javascript">
302
				jQuery(document).ready(function ($) {
303
					give_on_donation_import_start();
304
				});
305
			</script>
306
			<?php
307
		}
308
309
		/**
310
		 * Will return true if importing can be started or not else false.
311
		 *
312
		 * @since 1.8.13
313
		 */
314
		static function check_for_dropdown_or_import() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
315
			$return = true;
316
			if ( isset( $_REQUEST['mapto'] ) ) {
317
				$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...
318
				if ( false === in_array( 'form_title', $mapto ) && false === in_array( 'form_id', $mapto ) ) {
319
					Give_Admin_Settings::add_error( 'give-import-csv-form', __( 'Please select Form ID or Form Name options from the dropdown.', 'give' ) );
320
					$return = false;
321
				}
322
323
				if ( false === in_array( 'amount', $mapto ) ) {
324
					Give_Admin_Settings::add_error( 'give-import-csv-amount', __( 'Please select Amount option from the dropdown.', 'give' ) );
325
					$return = false;
326
				}
327
328
				if ( false === in_array( 'email', $mapto ) && false === in_array( 'donor_id', $mapto ) ) {
329
					Give_Admin_Settings::add_error( 'give-import-csv-donor', __( 'Please select Email id or Customer ID options from the dropdown.', 'give' ) );
330
					$return = false;
331
				}
332
			} else {
333
				$return = false;
334
			}
335
336
			return $return;
337
		}
338
339
		/**
340
		 * Print the Dropdown option for CSV.
341
		 *
342
		 * @since 1.8.13
343
		 */
344
		static function render_dropdown() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
345
			$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...
346
347
			// TO check if the CSV files that is being add is valid or not if not then redirect to first step again
348
			$has_error = self::csv_check( $csv );
0 ignored issues
show
Documentation introduced by
$csv is of type integer, but the function expects a 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...
349
			if ( $has_error ) {
350
				$url = give_import_page_url();
351
				?>
352
				<script type="text/javascript">
353
					window.location = "<?php echo $url; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$url'
Loading history...
354
				</script>
355
				<?php
356
			} else {
357
				?>
358
				<tr valign="top" class="give-import-dropdown">
359
					<th colspan="2">
360
						<h2 id="give-import-title"><?php esc_html_e( 'Map CSV fields to donations', 'give' ) ?></h2>
361
						<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>
362
					</th>
363
				</tr>
364
365
				<tr valign="top" class="give-import-dropdown">
366
					<th><b><?php esc_html_e( 'Column name', 'give' ); ?></b></th>
367
					<th><b><?php esc_html_e( 'Map to field', 'give' ); ?></b></th>
368
				</tr>
369
370
				<?php
371
				$raw_key   = self::get_importer( $csv );
372
				$donations = give_import_donations_options();
373
				$donors    = give_import_donor_options();
374
				$forms     = give_import_donation_form_options();
375
376
				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...
377
					?>
378
					<tr valign="top" class="give-import-option">
379
						<th><?php echo $value; ?></th>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$value'
Loading history...
380
						<th>
381
							<?php
382
							self::get_columns( $index, $donations, $donors, $forms, $value );
383
							?>
384
						</th>
385
					</tr>
386
					<?php
387
				}
388
			}
389
		}
390
391
		static function selected( $option_value, $value ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
392
			$selected = '';
393
			if ( stristr( $value, $option_value ) ) {
394
				$selected = 'selected';
395
			} elseif ( strrpos( $value, '_' ) && stristr( $option_value, 'Import as Meta' ) ) {
396
				$selected = 'selected';
397
			}
398
399
			return $selected;
400
		}
401
402
		/**
403
		 * Print the colums from the CSV.
404
		 *
405
		 * @since 1.8.13
406
		 */
407
		static function get_columns( $index, $donations, $donors, $forms, $value = false ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
408
			$default = give_import_default_options();
409
			?>
410
			<select name="mapto[<?php echo $index; ?>]">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$index'
Loading history...
411
				<?php
412 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...
413
					$checked = self::selected( $option_value, $value );
414
					?>
415
					<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...
416
					<?php
417
				}
418
				?>
419
				<optgroup label="Donations">
420
					<?php
421 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...
422
						$checked = self::selected( $option_value, $value );
423
						?>
424
						<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...
425
						<?php
426
					}
427
					?>
428
				</optgroup>
429
430
				<optgroup label="Donors">
431
					<?php
432 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...
433
						$checked = self::selected( $option_value, $value );
434
						?>
435
						<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...
436
						<?php
437
					}
438
					?>
439
				</optgroup>
440
441
				<optgroup label="Forms">
442
					<?php
443 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...
444
						$checked = self::selected( $option_value, $value );
445
						?>
446
						<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...
447
						<?php
448
					}
449
					?>
450
				</optgroup>
451
452
				<?php
453
				do_action( 'give_import_dropdown_option', $index, $donations, $donors, $forms, $value );
454
				?>
455
			</select>
456
			<?php
457
		}
458
459
		static function get_csv_total( $file_id ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
460
			$total = false;
461
			if ( $file_id ) {
462
				$file_dir = get_attached_file( $file_id );
463
				if ( $file_dir ) {
464
					$file = new SplFileObject( $file_dir, 'r' );
465
					$file->seek( PHP_INT_MAX );
466
					$total = $file->key() + 1;
467
				}
468
			}
469
470
			return $total;
471
		}
472
473
		/**
474
		 * Get the CSV fields title from the CSV.
475
		 *
476
		 * @since 1.8.13
477
		 *
478
		 * @param (int) $file_id
479
		 * @param int $index
480
		 * @param string $delimiter
481
		 *
482
		 * @return array|bool $raw_data title of the CSV file fields
483
		 */
484
		static function get_importer( $file_id, $index = 0, $delimiter = ',' ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
485
			$raw_data = false;
486
			$file_dir = get_attached_file( $file_id );
487
			if ( $file_dir ) {
488
				if ( false !== ( $handle = fopen( $file_dir, 'r' ) ) ) {
489
					$raw_data = fgetcsv( $handle, $index, $delimiter );
490
					// Remove BOM signature from the first item.
491
					if ( isset( $raw_data[0] ) ) {
492
						$raw_data[0] = self::remove_utf8_bom( $raw_data[0] );
493
					}
494
				}
495
			}
496
497
			return $raw_data;
498
		}
499
500
		/**
501
		 * Remove UTF-8 BOM signature.
502
		 *
503
		 * @since 1.8.13
504
		 *
505
		 * @param  string $string String to handle.
506
		 *
507
		 * @return string
508
		 */
509
		static function remove_utf8_bom( $string ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
510
			if ( 'efbbbf' === substr( bin2hex( $string ), 0, 6 ) ) {
511
				$string = substr( $string, 3 );
512
			}
513
514
			return $string;
515
		}
516
517
518
		/**
519
		 * Is used to show the process when user upload the donor form.
520
		 *
521
		 * @since 1.8.13
522
		 */
523
		static function progress() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
524
			$step = Give_Settings_Import::get_step();
525
			?>
526
			<ol class="give-progress-steps">
527
				<li class="<?php echo( 1 === $step ? 'active' : '' ); ?>"><?php esc_html_e( 'Upload CSV file', 'give' ); ?></li>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '('
Loading history...
528
				<li class="<?php echo( 2 === $step ? 'active' : '' ); ?>"><?php esc_html_e( 'Column mapping', 'give' ); ?></li>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '('
Loading history...
529
				<li class="<?php echo( 3 === $step ? 'active' : '' ); ?>"><?php esc_html_e( 'Import', 'give' ); ?></li>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '('
Loading history...
530
				<li class="<?php echo( 4 === $step ? 'active' : '' ); ?>"><?php esc_html_e( 'Done!', 'give' ); ?></li>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '('
Loading history...
531
			</ol>
532
			<?php
533
		}
534
535
		/**
536
		 * Will return the import step.
537
		 *
538
		 * @since 1.8.13
539
		 *
540
		 * @return int $step on which step doest the import is on.
541
		 */
542
		static function get_step() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
543
			$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...
544
			$on_step = 1;
545
			if ( empty( $step ) || 1 === $step ) {
546
				$on_step = 1;
547
			} elseif ( self::check_for_dropdown_or_import() ) {
548
				$on_step = 3;
549
			} elseif ( 2 === $step ) {
550
				$on_step = 2;
551
			} elseif ( 4 === $step ) {
552
				$on_step = 4;
553
			}
554
555
			return (int) $on_step;
556
		}
557
558
		/**
559
		 * Add CSV upload HTMl
560
		 *
561
		 * Print the html of the file upload from which CSV will be uploaded.
562
		 *
563
		 * @since 1.8.13
564
		 */
565
		static public function render_media_csv() {
566
			?>
567
			<tr valign="top">
568
				<th colspan="2">
569
					<h2 id="give-import-title"><?php esc_html_e( 'Import donations from a CSV file', 'give' ) ?></h2>
570
					<p class="give-field-description"><?php esc_html_e( 'This tool allows you to import (or merge) donation data to give from a CSV file.', 'give' ) ?></p>
571
				</th>
572
			</tr>
573
			<?php
574
			$csv         = ( isset( $_REQUEST['csv'] ) ? give_clean( $_POST['csv'] ) : '' );
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
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...
575
			$delimiter   = ( isset( $_REQUEST['delimiter'] ) ? give_clean( $_POST['delimiter'] ) : ',' );
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
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...
576
			$mode        = ( ! empty( $_REQUEST['mode'] ) ? 'on' : '' );
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
577
			$create_user = ( isset( $_REQUEST['create_user'] ) && isset( $_REQUEST['csv'] ) && 1 == absint( $_REQUEST['create_user'] ) ? 'on' : ( isset( $_REQUEST['csv'] ) ? '' : 'on' ) );
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
578
			$delete_csv = ( isset( $_REQUEST['delete_csv'] ) && isset( $_REQUEST['csv'] ) && 1 == absint( $_REQUEST['delete_csv'] ) ? 'on' : ( isset( $_REQUEST['csv'] ) ? '' : 'on' ) );
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
579
580
			$settings = array(
581
				array(
582
					'id'         => 'csv',
583
					'name'       => __( 'Choose a CSV file:', 'give' ),
584
					'type'       => 'file',
585
					'attributes' => array( 'editing' => 'false', 'library' => 'text' ),
586
					'fvalue'     => 'id',
587
					'default'    => $csv,
588
				),
589
				array(
590
					'id'         => 'delimiter',
591
					'name'       => __( 'CSV Delimiter:', 'give' ),
592
					'type'       => 'text',
593
					'attributes' => array( 'placeholder' => ',', 'size' => '2' ),
594
					'default'    => $delimiter,
595
				),
596
				array(
597
					'id'      => 'mode',
598
					'name'    => __( 'Test Mode:', 'give' ),
599
					'type'    => 'checkbox',
600
					'default' => $mode,
601
				),
602
				array(
603
					'id'      => 'create_user',
604
					'name'    => __( 'Create WP users for new donors?:', 'give' ),
605
					'type'    => 'checkbox',
606
					'default' => $create_user,
607
				),
608
				array(
609
					'id'      => 'delete_csv',
610
					'name'    => __( 'Delete CSV after import:', 'give' ),
611
					'type'    => 'checkbox',
612
					'default' => $delete_csv,
613
				),
614
			);
615
616
			$settings = apply_filters( 'give_import_file_upload_html', $settings );
617
618
			Give_Admin_Settings::output_fields( $settings, 'give_settings' );
619
		}
620
621
		/**
622
		 * Run when user click on the submit button.
623
		 *
624
		 * @since 1.8.13
625
		 */
626
		public function save() {
627
			// Get the current step.
628
			$step = Give_Settings_Import::get_step();
629
630
			// Validation for first step.
631
			if ( 1 === $step ) {
632
				$csv = absint( $_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-validated input variable: $_POST
Loading history...
633
634
				$has_error = self::csv_check( $csv );
635
636
				if ( false == $has_error ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
637
638
					$url = give_import_page_url( (array) apply_filters( 'give_import_step_two_url', array(
639
						'step'        => '2',
640
						'csv'         => $csv,
641
						'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...
642
						'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...
643
						'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...
644
						'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...
645
					) ) );
646
					?>
647
					<script type="text/javascript">
648
						window.location = "<?php echo $url; ?>"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$url'
Loading history...
649
					</script>
650
					<?php
651
				}
652
			}
653
		}
654
655
		/**
656
		 * Check if user uploaded csv is valid or not.
657
		 *
658
		 * @since 1.8.13
659
		 *
660
		 * param int $csv Id of the CSV files.
661
		 *
662
		 * return bool $has_error CSV is valid or not.
663
		 */
664
		static function csv_check( $csv = false ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
665
			$has_error = false;
666
			if ( $csv ) {
667
				if ( ! wp_get_attachment_url( $csv ) ) {
668
					$has_error = true;
669
					Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide the ID to a valid CSV file.', 'give' ) );
670
				} elseif ( ( $mime_type = get_post_mime_type( $csv ) ) && ! strpos( $mime_type, 'csv' ) ) {
671
					$has_error = true;
672
					Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide the ID to a valid CSV file.', 'give' ) );
673
				}
674
			} else {
675
				$has_error = true;
676
				Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide the ID to a valid CSV file.', 'give' ) );
677
			}
678
679
			return $has_error;
680
		}
681
682
		/**
683
		 * Add this page to settings.
684
		 *
685
		 * @since  1.8.13
686
		 *
687
		 * @param  array $pages Lst of pages.
688
		 *
689
		 * @return array
690
		 */
691
		public function add_settings_page( $pages ) {
692
			$pages[ $this->id ] = $this->label;
693
694
			return $pages;
695
		}
696
697
		/**
698
		 * Get settings array.
699
		 *
700
		 * @since  1.8.13
701
		 * @return array
702
		 */
703
		public function get_settings() {
704
			// Hide save button.
705
			$GLOBALS['give_hide_save_button'] = true;
706
707
			/**
708
			 * Filter the settings.
709
			 *
710
			 * @since  1.8.13
711
			 *
712
			 * @param  array $settings
713
			 */
714
			$settings = apply_filters(
715
				'give_get_settings_' . $this->id,
716
				array(
717
					array(
718
						'id'   => 'import',
719
						'name' => __( 'Import Donations', 'give' ),
720
						'type' => 'tools_import',
721
					),
722
				)
723
			);
724
725
			// Output.
726
			return $settings;
727
		}
728
729
		/**
730
		 * Output the settings.
731
		 *
732
		 * @since  1.8.13
733
		 * @return void
734
		 */
735
		public function output() {
736
			$settings = $this->get_settings();
737
			Give_Admin_Settings::output_fields( $settings, 'give_settings' );
738
		}
739
740
		/**
741
		 * Render report import field
742
		 *
743
		 * @since  1.8.13
744
		 * @access public
745
		 *
746
		 * @param $field
747
		 * @param $option_value
748
		 */
749
		public function render_import_field( $field, $option_value ) {
750
			include_once( 'views/html-admin-page-imports.php' );
751
		}
752
	}
753
}
754
return new Give_Settings_Import();
755