PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 3.6.1
GiveWP – Donation Plugin and Fundraising Platform v3.6.1
4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / includes / admin / tools / import / class-give-import-donations.php
give / includes / admin / tools / import Last commit date
class-give-import-core-settings.php 3 years ago class-give-import-donations.php 2 years ago
class-give-import-donations.php
1133 lines
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, GiveWP
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 private static $instance;
43
44 /**
45 * Importing donation per page.
46 *
47 * @since 1.8.14
48 *
49 * @var int
50 */
51 public static $per_page = 25;
52
53 /**
54 * Importing donation per page.
55 *
56 * @since 2.1
57 *
58 * @var int
59 */
60 public $is_csv_valid = false;
61
62 /**
63 * Singleton pattern.
64 *
65 * @since
66 * @access private
67 */
68 private function __construct() {
69 self::$per_page = ! empty( $_GET['per_page'] ) ? absint( $_GET['per_page'] ) : self::$per_page;
70 }
71
72 /**
73 * Get instance.
74 *
75 * @since
76 * @access public
77 *
78 * @return static
79 */
80 public static function get_instance() {
81 if ( null === static::$instance ) {
82 self::$instance = new static();
83 }
84
85 return self::$instance;
86 }
87
88 /**
89 * Setup
90 *
91 * @since 1.8.14
92 *
93 * @return void
94 */
95 public function setup() {
96 $this->setup_hooks();
97 }
98
99
100 /**
101 * Setup Hooks.
102 *
103 * @since 1.8.14
104 *
105 * @return void
106 */
107 private function setup_hooks() {
108 if ( ! $this->is_donations_import_page() ) {
109 return;
110 }
111
112 // Do not render main import tools page.
113 remove_action( 'give_admin_field_tools_import', array( 'Give_Settings_Import', 'render_import_field' ) );
114
115 // Render donation import page
116 add_action( 'give_admin_field_tools_import', array( $this, 'render_page' ) );
117
118 // Print the HTML.
119 add_action( 'give_tools_import_donations_form_start', array( $this, 'html' ), 10 );
120
121 // Run when form submit.
122 add_action( 'give-tools_save_import', array( $this, 'save' ) );
123
124 add_action( 'give-tools_update_notices', array( $this, 'update_notices' ), 11, 1 );
125
126 // Used to add submit button.
127 add_action( 'give_tools_import_donations_form_end', array( $this, 'submit' ), 10 );
128 }
129
130 /**
131 * Update notice
132 *
133 * @since 1.8.14
134 *
135 * @param $messages
136 *
137 * @return mixed
138 */
139 public function update_notices( $messages ) {
140 if ( ! empty( $_GET['tab'] ) && 'import' === give_clean( $_GET['tab'] ) ) {
141 unset( $messages['give-setting-updated'] );
142 }
143
144 return $messages;
145 }
146
147 /**
148 * Print submit and nonce button.
149 *
150 * @since 1.8.14
151 */
152 public function submit() {
153 wp_nonce_field( 'give-save-settings', '_give-save-settings' );
154 ?>
155 <input type="hidden" class="import-step" id="import-step" name="step"
156 value="<?php echo esc_attr($this->get_step()); ?>"/>
157 <input type="hidden" class="importer-type" value="<?php echo esc_attr($this->importer_type); ?>"/>
158 <?php
159 }
160
161 /**
162 * Print the HTML for importer.
163 *
164 * @since 1.8.14
165 */
166 public function html() {
167 $step = $this->get_step();
168
169 // Show progress.
170 $this->render_progress();
171 ?>
172 <section>
173 <table
174 class="widefat export-options-table give-table <?php echo esc_attr("step-{$step}"); ?> <?php echo esc_attr(( 1 === $step && ! empty( $this->is_csv_valid ) ? 'give-hidden' : '' )); ?> "
175 id="<?php echo esc_attr("step-{$step}"); ?>">
176 <tbody>
177 <?php
178 switch ( $step ) {
179 case 1:
180 $this->render_media_csv();
181 break;
182
183 case 2:
184 $this->render_dropdown();
185 break;
186
187 case 3:
188 $this->start_import();
189 break;
190
191 case 4:
192 $this->import_success();
193 }
194 if ( false === $this->check_for_dropdown_or_import() ) {
195 ?>
196 <tr valign="top">
197 <th>
198 <input type="submit"
199 class="button button-primary button-large button-secondary <?php echo esc_attr("step-{$step}"); ?>"
200 id="recount-stats-submit"
201 value="
202 <?php
203 /**
204 * Filter to modify donation importer submit button text.
205 *
206 * @since 2.1
207 */
208 echo esc_attr(apply_filters( 'give_import_donation_submit_button_text', __( 'Submit', 'give' ) ));
209 ?>
210 "/>
211 </th>
212 <th>
213 <?php
214 /**
215 * Action to add submit button description.
216 *
217 * @since 2.1
218 */
219 do_action( 'give_import_donation_submit_button' );
220 ?>
221 </th>
222 </tr>
223 <?php
224 }
225 ?>
226 </tbody>
227 </table>
228 </section>
229 <?php
230 }
231
232 /**
233 * Show success notice
234 *
235 * @since 2.25.3 Add nonce check.
236 * @since 1.8.14
237 */
238 public function import_success() {
239 check_admin_referer('give_donation_import_success');
240
241 $delete_csv = ( ! empty( $_GET['delete_csv'] ) ? absint( $_GET['delete_csv'] ) : false );
242 $csv = ( ! empty( $_GET['csv'] ) ? absint( $_GET['csv'] ) : false );
243 if ( ! empty( $delete_csv ) && ! empty( $csv ) ) {
244 wp_delete_attachment( $csv, true );
245 }
246
247 $report = give_import_donation_report();
248
249 $report_html = array(
250 'duplicate_donor' => array(
251 __( '%1$s duplicate %2$s detected', 'give' ),
252 __( '%1$s duplicate %2$s detected', 'give' ),
253 __( 'donor', 'give' ),
254 __( 'donors', 'give' ),
255 ),
256 'create_donor' => array(
257 __( '%1$s %2$s created', 'give' ),
258 __( '%1$s %2$s will be created', 'give' ),
259 __( 'donor', 'give' ),
260 __( 'donors', 'give' ),
261 ),
262 'create_form' => array(
263 __( '%1$s donation %2$s created', 'give' ),
264 __( '%1$s donation %2$s will be created', 'give' ),
265 __( 'form', 'give' ),
266 __( 'forms', 'give' ),
267 ),
268 'duplicate_donation' => array(
269 __( '%1$s duplicate %2$s detected', 'give' ),
270 __( '%1$s duplicate %2$s detected', 'give' ),
271 __( 'donation', 'give' ),
272 __( 'donations', 'give' ),
273 ),
274 'create_donation' => array(
275 __( '%1$s %2$s imported', 'give' ),
276 __( '%1$s %2$s will be imported', 'give' ),
277 __( 'donation', 'give' ),
278 __( 'donations', 'give' ),
279 ),
280 );
281 $total = (int) $_GET['total'];
282 -- $total;
283 $success = (bool) $_GET['success'];
284 $dry_run = empty( $_GET['dry_run'] ) ? 0 : absint( $_GET['dry_run'] );
285 ?>
286 <tr valign="top" class="give-import-dropdown">
287 <th colspan="2">
288 <h2>
289 <?php
290 if ( $success ) {
291 if ( $dry_run ) {
292 printf(
293 _n( 'Dry run import complete! %s donation processed', 'Dry run import complete! %s donations processed', $total, 'give' ),
294 "<strong>{$total}</strong>"
295 );
296 } else {
297 printf(
298 _n( 'Import complete! %s donation processed', 'Import complete! %s donations processed', $total, 'give' ),
299 "<strong>{$total}</strong>"
300 );
301 }
302 } else {
303 printf(
304 _n( 'Failed to import %s donation', 'Failed to import %s donations', $total, 'give' ),
305 "<strong>{$total}</strong>"
306 );
307 }
308 ?>
309 </h2>
310
311 <?php
312 $text = __( 'Import Donation', 'give' );
313 $query_arg = array(
314 'post_type' => 'give_forms',
315 'page' => 'give-tools',
316 'tab' => 'import',
317 );
318 if ( $success ) {
319
320 if ( $dry_run ) {
321 $query_arg = array(
322 'post_type' => 'give_forms',
323 'page' => 'give-tools',
324 'tab' => 'import',
325 'importer-type' => 'import_donations',
326 );
327
328 $text = __( 'Start Import', 'give' );
329 } else {
330 $query_arg = array(
331 'post_type' => 'give_forms',
332 'page' => 'give-payment-history',
333 );
334 $text = __( 'View Donations', 'give' );
335 }
336 }
337
338 foreach ( $report as $key => $value ) {
339 if ( array_key_exists( $key, $report_html ) && ! empty( $value ) ) {
340 $key_name = $report_html[ $key ][2];
341 if ( $value > 1 ) {
342 $key_name = $report_html[ $key ][3];
343 }
344 ?>
345 <p>
346 <?php printf( $report_html[ $key ][ $dry_run ], $value, $key_name ); ?>
347 </p>
348 <?php
349 }
350 }
351 ?>
352
353 <p>
354 <a class="button button-large button-secondary"
355 href="<?php echo esc_url( add_query_arg( $query_arg, admin_url( 'edit.php' ) ) ); ?>"><?php echo $text; ?></a>
356 </p>
357 </th>
358 </tr>
359 <?php
360 }
361
362 /**
363 * Will start Import
364 *
365 * @since 1.8.14
366 */
367 public function start_import() {
368 // Reset the donation form report.
369 give_import_donation_report_reset();
370
371 $csv = absint( $_REQUEST['csv'] );
372 $delimiter = ( ! empty( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : 'csv' );
373 $index_start = 1;
374 $next = true;
375 $total = self::get_csv_total( $csv );
376 if ( self::$per_page < $total ) {
377 $total_ajax = ceil( $total / self::$per_page );
378 $index_end = self::$per_page;
379 } else {
380 $total_ajax = 1;
381 $index_end = $total;
382 $next = false;
383 }
384 $current_percentage = 100 / ( $total_ajax + 1 );
385
386 ?>
387 <tr valign="top" class="give-import-dropdown">
388 <th colspan="2">
389 <h2 id="give-import-title"><?php _e( 'Importing', 'give' ); ?></h2>
390 <p class="give-field-description"><?php _e( 'Your donations are now being imported...', 'give' ); ?></p>
391 </th>
392 </tr>
393
394 <tr valign="top" class="give-import-dropdown">
395 <th colspan="2">
396 <span class="spinner is-active"></span>
397 <div class="give-progress"
398 data-current="1"
399 data-total_ajax="<?php echo esc_attr(absint( $total_ajax )); ?>"
400 data-start="<?php echo esc_attr(absint( $index_start )); ?>"
401 data-end="<?php echo esc_attr(absint( $index_end )); ?>"
402 data-next="<?php echo esc_attr(absint( $next )); ?>"
403 data-total="<?php echo esc_attr(absint( $total )); ?>"
404 data-per_page="<?php echo esc_attr(absint( self::$per_page )); ?>">
405
406 <div style="width: <?php echo esc_attr((float) $current_percentage); ?>%"></div>
407 </div>
408 <input type="hidden" value="3" name="step">
409 <input type="hidden" value='<?php echo esc_attr( maybe_serialize( $_REQUEST['mapto'] ) ); ?>' name="mapto" class="mapto">
410 <input type="hidden" value="<?php echo esc_attr($csv); ?>" name="csv" class="csv">
411 <input type="hidden" value="<?php echo esc_attr( $_REQUEST['mode'] ); ?>" name="mode" class="mode">
412 <input type="hidden" value="<?php echo esc_attr( $_REQUEST['create_user'] ); ?>" name="create_user" class="create_user">
413 <input type="hidden" value="<?php echo esc_attr( $_REQUEST['delete_csv'] ); ?>" name="delete_csv" class="delete_csv">
414 <input type="hidden" value="<?php echo esc_attr( $delimiter ); ?>" name="delimiter">
415 <input type="hidden" value="<?php echo esc_attr(absint( $_REQUEST['dry_run']) ); ?>" name="dry_run">
416 <input type="hidden" value='<?php echo esc_attr( maybe_serialize( self::get_importer( $csv, 0, $delimiter ) ) ); ?>' name="main_key" class="main_key">
417 </th>
418 </tr>
419 <?php
420 }
421
422 /**
423 * Will return true if importing can be started or not else false.
424 *
425 * @since 1.8.14
426 */
427 public function check_for_dropdown_or_import() {
428 $return = true;
429 if ( isset( $_REQUEST['mapto'] ) ) {
430 $mapto = (array) $_REQUEST['mapto'];
431 if ( false === in_array( 'form_title', $mapto ) && false === in_array( 'form_id', $mapto ) ) {
432 Give_Admin_Settings::add_error( 'give-import-csv-form', __( 'In order to import donations, a column must be mapped to either the "Donation Form Title" or "Donation Form ID" field. Please map a column to one of those fields.', 'give' ) );
433 $return = false;
434 }
435
436 if ( false === in_array( 'amount', $mapto ) ) {
437 Give_Admin_Settings::add_error( 'give-import-csv-amount', __( 'In order to import donations, a column must be mapped to the "Amount" field. Please map a column to that field.', 'give' ) );
438 $return = false;
439 }
440
441 if ( false === in_array( 'email', $mapto ) && false === in_array( 'donor_id', $mapto ) ) {
442 Give_Admin_Settings::add_error( 'give-import-csv-donor', __( 'In order to import donations, a column must be mapped to either the "Donor Email" or "Donor ID" field. Please map a column to that field.', 'give' ) );
443 $return = false;
444 }
445 } else {
446 $return = false;
447 }
448
449 return $return;
450 }
451
452 /**
453 * Print the Dropdown option for CSV.
454 *
455 * @since 1.8.14
456 */
457 public function render_dropdown() {
458 if (!$this->is_nonce_valid()) {
459 Give_Admin_Settings::add_error( 'give-import-csv', __( 'Something went wrong.', 'give' ) );
460 ?>
461 <input type="hidden" name="csv_not_valid" class="csv_not_valid" value="<?php echo esc_attr(give_import_page_url()); ?>"/>
462 <?php
463 wp_die();
464 }
465
466 $csv = (int) $_GET['csv'];
467 $delimiter = ( ! empty( $_GET['delimiter'] ) ? give_clean( $_GET['delimiter'] ) : 'csv' );
468
469 // TO check if the CSV files that is being add is valid or not if not then redirect to first step again
470 if ( ! $this->is_valid_csv( $csv ) ) {
471 $url = give_import_page_url();
472 ?>
473 <input type="hidden" name="csv_not_valid" class="csv_not_valid" value="<?php echo esc_attr($url); ?>"/>
474 <?php
475 } else {
476 ?>
477 <tr valign="top" class="give-import-dropdown">
478 <th colspan="2">
479 <h2 id="give-import-title"><?php _e( 'Map CSV fields to donations', 'give' ); ?></h2>
480
481 <p class="give-import-donation-required-fields-title"><?php _e( 'Required Fields', 'give' ); ?></p>
482
483 <p class="give-field-description"><?php _e( 'These fields are required for the import to submitted', 'give' ); ?></p>
484
485 <ul class="give-import-donation-required-fields">
486 <li class="give-import-donation-required-email"
487 title="Please configure all required fields to start the import process.">
488 <span class="give-import-donation-required-symbol dashicons dashicons-no-alt"></span>
489 <span class="give-import-donation-required-text">
490 <?php
491 _e( 'Email Address', 'give' );
492 ?>
493 </span>
494 </li>
495
496 <li class="give-import-donation-required-first"
497 title="Please configure all required fields to start the import process.">
498 <span class="give-import-donation-required-symbol dashicons dashicons-no-alt"></span>
499 <span class="give-import-donation-required-text">
500 <?php
501 _e( 'First Name', 'give' );
502 ?>
503 </span>
504 </li>
505
506 <li class="give-import-donation-required-amount"
507 title="Please configure all required fields to start the import process.">
508 <span class="give-import-donation-required-symbol dashicons dashicons-no-alt"></span>
509 <span class="give-import-donation-required-text">
510 <?php
511 _e( 'Donation Amount', 'give' );
512 ?>
513 </span>
514 </li>
515
516 <li class="give-import-donation-required-form"
517 title="Please configure all required fields to start the import process.">
518 <span class="give-import-donation-required-symbol dashicons dashicons-no-alt"></span>
519 <span class="give-import-donation-required-text">
520 <?php
521 _e( 'Form Title or ID', 'give' );
522 ?>
523 </span>
524 </li>
525 </ul>
526
527 <p class="give-field-description"><?php _e( 'Select fields from your CSV file to map against donations fields or to ignore during import.', 'give' ); ?></p>
528 </th>
529 </tr>
530
531 <tr valign="top" class="give-import-dropdown">
532 <th><b><?php _e( 'Column name', 'give' ); ?></b></th>
533 <th><b><?php _e( 'Map to field', 'give' ); ?></b></th>
534 </tr>
535
536 <?php
537
538 $selectedOptions = []; // Initialize the tracking array for selected options
539
540 $raw_key = $this->get_importer( $csv, 0, $delimiter );
541 $mapto = (array) ( isset( $_REQUEST['mapto'] ) ? $_REQUEST['mapto'] : array() );
542
543 foreach ( $raw_key as $index => $value ) {
544 ?>
545 <tr valign="middle" class="give-import-option">
546 <th><?php echo esc_html($value); ?></th>
547 <th>
548 <?php
549 $this->get_columns( $index, $value, $mapto, $selectedOptions );
550 ?>
551 </th>
552 </tr>
553 <?php
554 }
555 }
556 }
557
558 /**
559 * @param $option_value
560 * @param $value
561 *
562 * @return string
563 */
564 public function selected( $option_value, $value ) {
565 $option_value = strtolower( $option_value );
566 $value = strtolower( $value );
567
568 $selected = '';
569 if ( stristr( $value, $option_value ) ) {
570 $selected = 'selected';
571 } elseif ( strrpos( $value, 'give_' ) && stristr( $option_value, __( 'Import as Meta', 'give' ) ) ) {
572 $selected = 'selected';
573 }
574
575 return $selected;
576 }
577
578 /**
579 * Print the columns from the CSV.
580 *
581 * @since 1.8.14
582 * @access private
583 *
584 * @param string $index
585 * @param bool $value
586 * @param array $mapto
587 * @param array $selectedOptions
588 *
589 * @return void
590 */
591 private function get_columns( $index, $value = false, $mapto = array(), &$selectedOptions = array() ) {
592 $default = give_import_default_options();
593 $current_mapto = (string) ( ! empty( $mapto[ $index ] ) ? $mapto[ $index ] : '' );
594 ?>
595 <select name="mapto[<?php echo esc_attr($index); ?>]">
596 <?php $this->get_dropdown_option_html( $default, $current_mapto, $value, $selectedOptions ); ?>
597
598 <optgroup label="<?php _e( 'Donations', 'give' ); ?>">
599 <?php
600 $this->get_dropdown_option_html( give_import_donations_options(), $current_mapto, $value, $selectedOptions );
601 ?>
602 </optgroup>
603
604 <optgroup label="<?php _e( 'Donors', 'give' ); ?>">
605 <?php
606 $this->get_dropdown_option_html( give_import_donor_options(), $current_mapto, $value, $selectedOptions );
607 ?>
608 </optgroup>
609
610 <optgroup label="<?php _e( 'Forms', 'give' ); ?>">
611 <?php
612 $this->get_dropdown_option_html( give_import_donation_form_options(), $current_mapto, $value, $selectedOptions );
613 ?>
614 </optgroup>
615
616 <?php
617 /**
618 * Fire the action
619 * You can use this filter to add new options.
620 *
621 * @since 1.8.15
622 */
623 do_action( 'give_import_dropdown_option', $index, $value, $mapto, $current_mapto );
624 ?>
625 </select>
626 <?php
627 }
628
629 /**
630 * Print the option html for select in importer
631 *
632 * @since 1.8.15
633 * @access public
634 *
635 * @param array $options
636 * @param string $current_mapto
637 * @param bool $value
638 * @param array $selectedOptions
639 *
640 * @return void
641 */
642 public function get_dropdown_option_html( $options, $current_mapto, $value = false, &$selectedOptions = array() ) {
643 foreach ( $options as $option => $option_value ) {
644 $ignore = array();
645 if ( isset( $option_value['ignore'] ) && is_array( $option_value['ignore'] ) ) {
646 $ignore = $option_value['ignore'];
647 unset( $option_value['ignore'] );
648 }
649
650 $option_value_texts = (array) $option_value;
651 $option_text = $option_value_texts[0];
652
653 // Initialize selected as false
654 $selected = false;
655
656 // If current field matches option and it's not already selected, mark as selected
657 if ( $current_mapto === $option && !in_array($option, $selectedOptions) ) {
658 $selected = 'selected';
659 $selectedOptions[] = $option; // Add to selected options
660 } else {
661 // Check against option value texts if not already selected
662 if ( ! in_array( $value, $ignore ) && !in_array($option, $selectedOptions) ) {
663 foreach ( $option_value_texts as $option_value_text ) {
664 $selected = $this->selected( $option_value_text, $value );
665 if ( $selected ) {
666 $selectedOptions[] = $option; // Add to selected options
667 break;
668 }
669 }
670 }
671 }
672 ?>
673 <option value="<?php echo esc_attr($option); ?>" <?php echo esc_html($selected); ?> ><?php echo esc_html($option_text); ?></option>
674 <?php
675 }
676 }
677
678
679 /**
680 * Get column count of csv file.
681 *
682 * @since 1.8.14
683 *
684 * @param $file_id
685 *
686 * @return bool|int
687 */
688 public function get_csv_total( $file_id ) {
689 $total = false;
690 if ( $file_id ) {
691 $file_dir = get_attached_file( $file_id );
692 if ( $file_dir ) {
693 $total = $this->get_csv_data_from_file_dir( $file_dir );
694 }
695 }
696
697 return $total;
698 }
699
700 /**
701 * Get data from File
702 *
703 * @since 2.1
704 *
705 * @param $file_dir
706 *
707 * @return bool|int
708 */
709 public function get_csv_data_from_file_dir( $file_dir ) {
710 $total = false;
711 if ( $file_dir ) {
712 $file = new SplFileObject( $file_dir, 'r' );
713 $file->seek( PHP_INT_MAX );
714 $total = $file->key() + 1;
715 }
716
717 return $total;
718 }
719
720 /**
721 * Get the CSV fields title from the CSV.
722 *
723 * @since 1.8.14
724 *
725 * @param (int) $file_id
726 * @param int $index
727 * @param string $delimiter
728 *
729 * @return array|bool $raw_data title of the CSV file fields
730 */
731 public function get_importer( $file_id, $index = 0, $delimiter = 'csv' ) {
732 /**
733 * Filter to modify delimiter of Import.
734 *
735 * @since 1.8.14
736 *
737 * Return string $delimiter.
738 */
739 $delimiter = (string) apply_filters( 'give_import_delimiter_set', $delimiter );
740
741 $raw_data = false;
742 $file_dir = get_attached_file( $file_id );
743 if ( $file_dir ) {
744 if ( false !== ( $handle = fopen( $file_dir, 'r' ) ) ) {
745 $raw_data = fgetcsv( $handle, $index, $delimiter );
746 // Remove BOM signature from the first item.
747 if ( isset( $raw_data[0] ) ) {
748 $raw_data[0] = $this->remove_utf8_bom( $raw_data[0] );
749 }
750 }
751 }
752
753 return $raw_data;
754 }
755
756 /**
757 * Remove UTF-8 BOM signature.
758 *
759 * @since 1.8.14
760 *
761 * @param string $string String to handle.
762 *
763 * @return string
764 */
765 public function remove_utf8_bom( $string ) {
766 if ( 'efbbbf' === substr( bin2hex( $string ), 0, 6 ) ) {
767 $string = substr( $string, 3 );
768 }
769
770 return $string;
771 }
772
773 /**
774 * Is used to show the process when user upload the donor form.
775 *
776 * @since 1.8.14
777 */
778 public function render_progress() {
779 $step = $this->get_step();
780 ?>
781 <ol class="give-progress-steps">
782 <li class="<?php echo esc_attr( 1 === $step ? 'active' : '' ); ?>">
783 <?php _e( 'Upload CSV file', 'give' ); ?>
784 </li>
785 <li class="<?php echo esc_attr( 2 === $step ? 'active' : '' ); ?>">
786 <?php _e( 'Column mapping', 'give' ); ?>
787 </li>
788 <li class="<?php echo esc_attr( 3 === $step ? 'active' : '' ); ?>">
789 <?php _e( 'Import', 'give' ); ?>
790 </li>
791 <li class="<?php echo esc_attr( 4 === $step ? 'active' : '' ); ?>">
792 <?php _e( 'Done!', 'give' ); ?>
793 </li>
794 </ol>
795 <?php
796 }
797
798 /**
799 * Will return the import step.
800 *
801 * @since 1.8.14
802 *
803 * @return int $step on which step doest the import is on.
804 */
805 public function get_step() {
806 $step = (int) ( isset( $_REQUEST['step'] ) ? give_clean( $_REQUEST['step'] ) : 0 );
807 $on_step = 1;
808
809 if ( empty( $step ) || 1 === $step ) {
810 $on_step = 1;
811 } elseif ( $this->check_for_dropdown_or_import() ) {
812 $on_step = 3;
813 } elseif ( 2 === $step ) {
814 $on_step = 2;
815 } elseif ( 4 === $step ) {
816 $on_step = 4;
817 }
818
819 return $on_step;
820 }
821
822 /**
823 * Render donations import page
824 *
825 * @since 1.8.14
826 */
827 public function render_page() {
828 include_once GIVE_PLUGIN_DIR . 'includes/admin/tools/views/html-admin-page-import-donations.php';
829 }
830
831 /**
832 * Print Dry Run HTML on donation import page
833 *
834 * @since 2.1
835 */
836 public function give_import_donation_submit_button_render_media_csv() {
837 $dry_run = isset( $_POST['dry_run'] ) ? absint( $_POST['dry_run'] ) : 1;
838 ?>
839 <div>
840 <label for="dry_run">
841 <input type="hidden" name="dry_run" value="0"/>
842 <input type="checkbox" name="dry_run" id="dry_run" class="dry_run"
843 value="1" <?php checked( 1, $dry_run ); ?> >
844 <strong><?php _e( 'Dry Run', 'give' ); ?></strong>
845 </label>
846 <p class="give-field-description">
847 <?php
848 _e( 'Preview what the import would look like without making any default changes to your site or your database.', 'give' );
849 ?>
850 </p>
851 </div>
852 <?php
853 }
854
855 /**
856 * Change submit button text on first step of importing donation.
857 *
858 * @since 2.1
859 *
860 * @param $text
861 *
862 * @return string
863 */
864 function give_import_donation_submit_text_render_media_csv( $text ) {
865 return __( 'Begin Import', 'give' );
866 }
867
868 /**
869 * Add CSV upload HTMl
870 *
871 * Print the html of the file upload from which CSV will be uploaded.
872 *
873 * @since 1.8.14
874 * @return void
875 */
876 public function render_media_csv() {
877 add_filter(
878 'give_import_donation_submit_button_text',
879 array(
880 $this,
881 'give_import_donation_submit_text_render_media_csv',
882 )
883 );
884 add_action(
885 'give_import_donation_submit_button',
886 array(
887 $this,
888 'give_import_donation_submit_button_render_media_csv',
889 )
890 );
891 ?>
892 <tr valign="top">
893 <th colspan="2">
894 <h2 id="give-import-title"><?php _e( 'Import donations from a CSV file', 'give' ); ?></h2>
895 <p class="give-field-description"><?php _e( 'This tool allows you to import or add donation data to your give form(s) via a CSV file.', 'give' ); ?></p>
896 </th>
897 </tr>
898 <?php
899 $csv = ( isset( $_POST['csv'] ) ? give_clean( $_POST['csv'] ) : '' );
900 $csv_id = ( isset( $_POST['csv_id'] ) ? give_clean( $_POST['csv_id'] ) : '' );
901 $delimiter = ( isset( $_POST['delimiter'] ) ? give_clean( $_POST['delimiter'] ) : 'csv' );
902 $mode = empty( $_POST['mode'] ) ?
903 'disabled' :
904 ( give_is_setting_enabled( give_clean( $_POST['mode'] ) ) ? 'enabled' : 'disabled' );
905 $create_user = empty( $_POST['create_user'] ) ?
906 'disabled' :
907 ( give_is_setting_enabled( give_clean( $_POST['create_user'] ) ) ? 'enabled' : 'disabled' );
908 $delete_csv = empty( $_POST['delete_csv'] ) ?
909 'enabled' :
910 ( give_is_setting_enabled( give_clean( $_POST['delete_csv'] ) ) ? 'enabled' : 'disabled' );
911
912 // Reset csv and csv_id if csv
913 if ( empty( $csv_id ) || ! $this->is_valid_csv( $csv_id, $csv ) ) {
914 $csv_id = $csv = '';
915 }
916 $per_page = isset( $_POST['per_page'] ) ? absint( $_POST['per_page'] ) : self::$per_page;
917
918 $sample_file_text = sprintf(
919 '%s <a href="%s">%s</a>.',
920 __( 'Download the sample file', 'give' ),
921 esc_url( GIVE_PLUGIN_URL . 'sample-data/sample-data.csv' ),
922 __( 'here', 'give' )
923 );
924
925 $csv_description = sprintf(
926 '%1$s %2$s',
927 __( 'The file must be a Comma Seperated Version (CSV) file type only.', 'give' ),
928 $sample_file_text
929 );
930
931 $settings = array(
932 array(
933 'id' => 'csv',
934 'name' => __( 'Choose a CSV file:', 'give' ),
935 'type' => 'file',
936 'attributes' => array(
937 'editing' => 'false',
938 'library' => 'text',
939 ),
940 'description' => $csv_description,
941 'fvalue' => 'url',
942 'default' => $csv,
943 ),
944 array(
945 'id' => 'csv_id',
946 'type' => 'hidden',
947 'value' => $csv_id,
948 ),
949 array(
950 'id' => 'delimiter',
951 'name' => __( 'CSV Delimiter:', 'give' ),
952 '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' ),
953 'default' => $delimiter,
954 'type' => 'select',
955 'options' => array(
956 'csv' => __( 'Comma', 'give' ),
957 'tab-separated-values' => __( 'Tab', 'give' ),
958 ),
959 ),
960 array(
961 'id' => 'mode',
962 'name' => __( 'Test Mode:', 'give' ),
963 'description' => __( 'Select whether you would like these donations to be marked as "test" donations within the database. By default, they will be marked as live donations.', 'give' ),
964 'default' => $mode,
965 'type' => 'radio_inline',
966 'options' => array(
967 'enabled' => __( 'Enabled', 'give' ),
968 'disabled' => __( 'Disabled', 'give' ),
969 ),
970 ),
971 array(
972 'id' => 'create_user',
973 'name' => __( 'Create WP users for new donors:', 'give' ),
974 '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' ),
975 'default' => $create_user,
976 'type' => 'radio_inline',
977 'options' => array(
978 'enabled' => __( 'Enabled', 'give' ),
979 'disabled' => __( 'Disabled', 'give' ),
980 ),
981 ),
982 array(
983 'id' => 'delete_csv',
984 'name' => __( 'Delete CSV after import:', 'give' ),
985 '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' ),
986 'default' => $delete_csv,
987 'type' => 'radio_inline',
988 'options' => array(
989 'enabled' => __( 'Enabled', 'give' ),
990 'disabled' => __( 'Disabled', 'give' ),
991 ),
992 ),
993 array(
994 'id' => 'per_page',
995 'name' => __( 'Process Rows Per Batch:', 'give' ),
996 'type' => 'number',
997 'description' => __( 'Determine how many rows you would like to import per cycle.', 'give' ),
998 'default' => $per_page,
999 'class' => 'give-text-small',
1000 ),
1001 );
1002
1003 $settings = apply_filters( 'give_import_file_upload_html', $settings );
1004
1005 if ( empty( $this->is_csv_valid ) ) {
1006 Give_Admin_Settings::output_fields( $settings, 'give_settings' );
1007 } else {
1008 ?>
1009 <input type="hidden" name="is_csv_valid" class="is_csv_valid"
1010 value="<?php echo esc_attr($this->is_csv_valid); ?>">
1011 <?php
1012 }
1013 }
1014
1015 /**
1016 * Run when user click on the submit button.
1017 *
1018 * @since 1.8.14
1019 */
1020 public function save() {
1021 if (!$this->is_nonce_valid()){
1022 wp_die();
1023 }
1024 // Get the current step.
1025 $step = $this->get_step();
1026
1027 // Validation for first step.
1028 if ( 1 === $step ) {
1029 $csv_id = absint( $_POST['csv_id'] );
1030
1031 if ( $this->is_valid_csv( $csv_id, esc_url( $_POST['csv'] ) ) ) {
1032
1033 $url = give_import_page_url(
1034 (array) apply_filters(
1035 'give_import_step_two_url',
1036 array(
1037 'step' => '2',
1038 'importer-type' => $this->importer_type,
1039 'csv' => $csv_id,
1040 'delimiter' => isset( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : 'csv',
1041 'mode' => empty( $_POST['mode'] ) ?
1042 '0' :
1043 ( give_is_setting_enabled( give_clean( $_POST['mode'] ) ) ? '1' : '0' ),
1044 'create_user' => empty( $_POST['create_user'] ) ?
1045 '0' :
1046 ( give_is_setting_enabled( give_clean( $_POST['create_user'] ) ) ? '1' : '0' ),
1047 'delete_csv' => empty( $_POST['delete_csv'] ) ?
1048 '1' :
1049 ( give_is_setting_enabled( give_clean( $_POST['delete_csv'] ) ) ? '1' : '0' ),
1050 'per_page' => isset( $_POST['per_page'] ) ? absint( $_POST['per_page'] ) : self::$per_page,
1051 'dry_run' => isset( $_POST['dry_run'] ) ? absint( $_POST['dry_run'] ) : 0,
1052 )
1053 )
1054 );
1055
1056 $this->is_csv_valid = wp_nonce_url($url, 'give-save-settings', '_give-save-settings');
1057 }
1058 }
1059 }
1060
1061 /**
1062 * Check if user uploaded csv is valid or not.
1063 *
1064 * @since 1.8.14
1065 * @access public
1066 *
1067 * @param mixed $csv ID of the CSV files.
1068 * @param string $match_url ID of the CSV files.
1069 *
1070 * @return bool $has_error CSV is valid or not.
1071 */
1072 private function is_valid_csv( $csv = false, $match_url = '' ) {
1073 $is_valid_csv = true;
1074
1075 if ( $csv ) {
1076 $csv_url = wp_get_attachment_url( $csv );
1077
1078 $delimiter = ( ! empty( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : 'csv' );
1079
1080 if (
1081 ! $csv_url ||
1082 ( ! empty( $match_url ) && ( $csv_url !== $match_url ) ) ||
1083 ( ( $mime_type = get_post_mime_type( $csv ) ) && ! strpos( $mime_type, $delimiter ) )
1084 ) {
1085 $is_valid_csv = false;
1086 Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid CSV file.', 'give' ) );
1087 }
1088 } else {
1089 $is_valid_csv = false;
1090 Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid CSV file.', 'give' ) );
1091 }
1092
1093 return $is_valid_csv;
1094 }
1095
1096
1097 /**
1098 * Render report import field
1099 *
1100 * @since 1.8.14
1101 * @access public
1102 *
1103 * @param $field
1104 * @param $option_value
1105 */
1106 public function render_import_field( $field, $option_value ) {
1107 include_once GIVE_PLUGIN_DIR . 'includes/admin/tools/views/html-admin-page-imports.php';
1108 }
1109
1110 /**
1111 * Get if current page import donations page or not
1112 *
1113 * @since 1.8.14
1114 * @return bool
1115 */
1116 private function is_donations_import_page() {
1117 return 'import' === give_get_current_setting_tab() &&
1118 isset( $_GET['importer-type'] ) &&
1119 $this->importer_type === give_clean( $_GET['importer-type'] );
1120 }
1121
1122 /**
1123 * @since 2.25.2
1124 */
1125 private function is_nonce_valid()
1126 {
1127 return !empty($_REQUEST['_give-save-settings']) && wp_verify_nonce($_REQUEST['_give-save-settings'], 'give-save-settings');
1128 }
1129 }
1130
1131 Give_Import_Donations::get_instance()->setup();
1132 }
1133