PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.29.2
GiveWP – Donation Plugin and Fundraising Platform v2.29.2
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 3 years ago
class-give-import-donations.php
1118 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 $raw_key = $this->get_importer( $csv, 0, $delimiter );
538 $mapto = (array) ( isset( $_REQUEST['mapto'] ) ? $_REQUEST['mapto'] : array() );
539
540 foreach ( $raw_key as $index => $value ) {
541 ?>
542 <tr valign="middle" class="give-import-option">
543 <th><?php echo esc_html($value); ?></th>
544 <th>
545 <?php
546 $this->get_columns( $index, $value, $mapto );
547 ?>
548 </th>
549 </tr>
550 <?php
551 }
552 }
553 }
554
555 /**
556 * @param $option_value
557 * @param $value
558 *
559 * @return string
560 */
561 public function selected( $option_value, $value ) {
562 $option_value = strtolower( $option_value );
563 $value = strtolower( $value );
564
565 $selected = '';
566 if ( stristr( $value, $option_value ) ) {
567 $selected = 'selected';
568 } elseif ( strrpos( $value, 'give_' ) && stristr( $option_value, __( 'Import as Meta', 'give' ) ) ) {
569 $selected = 'selected';
570 }
571
572 return $selected;
573 }
574
575 /**
576 * Print the columns from the CSV.
577 *
578 * @since 1.8.14
579 * @access private
580 *
581 * @param string $index
582 * @param bool $value
583 * @param array $mapto
584 *
585 * @return void
586 */
587 private function get_columns( $index, $value = false, $mapto = array() ) {
588 $default = give_import_default_options();
589 $current_mapto = (string) ( ! empty( $mapto[ $index ] ) ? $mapto[ $index ] : '' );
590 ?>
591 <select name="mapto[<?php echo esc_attr($index); ?>]">
592 <?php $this->get_dropdown_option_html( $default, $current_mapto, $value ); ?>
593
594 <optgroup label="<?php _e( 'Donations', 'give' ); ?>">
595 <?php
596 $this->get_dropdown_option_html( give_import_donations_options(), $current_mapto, $value );
597 ?>
598 </optgroup>
599
600 <optgroup label="<?php _e( 'Donors', 'give' ); ?>">
601 <?php
602 $this->get_dropdown_option_html( give_import_donor_options(), $current_mapto, $value );
603 ?>
604 </optgroup>
605
606 <optgroup label="<?php _e( 'Forms', 'give' ); ?>">
607 <?php
608 $this->get_dropdown_option_html( give_import_donation_form_options(), $current_mapto, $value );
609 ?>
610 </optgroup>
611
612 <?php
613 /**
614 * Fire the action
615 * You can use this filter to add new options.
616 *
617 * @since 1.8.15
618 */
619 do_action( 'give_import_dropdown_option', $index, $value, $mapto, $current_mapto );
620 ?>
621 </select>
622 <?php
623 }
624
625 /**
626 * Print the option html for select in importer
627 *
628 * @since 1.8.15
629 * @access public
630 *
631 * @param array $options
632 * @param string $current_mapto
633 * @param bool $value
634 *
635 * @return void
636 */
637 public function get_dropdown_option_html( $options, $current_mapto, $value = false ) {
638
639 foreach ( $options as $option => $option_value ) {
640 $ignore = array();
641 if ( isset( $option_value['ignore'] ) && is_array( $option_value['ignore'] ) ) {
642 $ignore = $option_value['ignore'];
643 unset( $option_value['ignore'] );
644 }
645
646 $option_value_texts = (array) $option_value;
647 $option_text = $option_value_texts[0];
648
649 $checked = ( ( $current_mapto === $option ) ? 'selected' : false );
650 if ( empty( $checked ) && ! in_array( $value, $ignore ) ) {
651 foreach ( $option_value_texts as $option_value_text ) {
652 $checked = $this->selected( $option_value_text, $value );
653 if ( $checked ) {
654 break;
655 }
656 }
657 }
658 ?>
659 <option value="<?php echo esc_attr($option); ?>" <?php echo esc_attr($checked); ?> ><?php echo esc_html($option_text); ?></option>
660 <?php
661 }
662 }
663
664 /**
665 * Get column count of csv file.
666 *
667 * @since 1.8.14
668 *
669 * @param $file_id
670 *
671 * @return bool|int
672 */
673 public function get_csv_total( $file_id ) {
674 $total = false;
675 if ( $file_id ) {
676 $file_dir = get_attached_file( $file_id );
677 if ( $file_dir ) {
678 $total = $this->get_csv_data_from_file_dir( $file_dir );
679 }
680 }
681
682 return $total;
683 }
684
685 /**
686 * Get data from File
687 *
688 * @since 2.1
689 *
690 * @param $file_dir
691 *
692 * @return bool|int
693 */
694 public function get_csv_data_from_file_dir( $file_dir ) {
695 $total = false;
696 if ( $file_dir ) {
697 $file = new SplFileObject( $file_dir, 'r' );
698 $file->seek( PHP_INT_MAX );
699 $total = $file->key() + 1;
700 }
701
702 return $total;
703 }
704
705 /**
706 * Get the CSV fields title from the CSV.
707 *
708 * @since 1.8.14
709 *
710 * @param (int) $file_id
711 * @param int $index
712 * @param string $delimiter
713 *
714 * @return array|bool $raw_data title of the CSV file fields
715 */
716 public function get_importer( $file_id, $index = 0, $delimiter = 'csv' ) {
717 /**
718 * Filter to modify delimiter of Import.
719 *
720 * @since 1.8.14
721 *
722 * Return string $delimiter.
723 */
724 $delimiter = (string) apply_filters( 'give_import_delimiter_set', $delimiter );
725
726 $raw_data = false;
727 $file_dir = get_attached_file( $file_id );
728 if ( $file_dir ) {
729 if ( false !== ( $handle = fopen( $file_dir, 'r' ) ) ) {
730 $raw_data = fgetcsv( $handle, $index, $delimiter );
731 // Remove BOM signature from the first item.
732 if ( isset( $raw_data[0] ) ) {
733 $raw_data[0] = $this->remove_utf8_bom( $raw_data[0] );
734 }
735 }
736 }
737
738 return $raw_data;
739 }
740
741 /**
742 * Remove UTF-8 BOM signature.
743 *
744 * @since 1.8.14
745 *
746 * @param string $string String to handle.
747 *
748 * @return string
749 */
750 public function remove_utf8_bom( $string ) {
751 if ( 'efbbbf' === substr( bin2hex( $string ), 0, 6 ) ) {
752 $string = substr( $string, 3 );
753 }
754
755 return $string;
756 }
757
758 /**
759 * Is used to show the process when user upload the donor form.
760 *
761 * @since 1.8.14
762 */
763 public function render_progress() {
764 $step = $this->get_step();
765 ?>
766 <ol class="give-progress-steps">
767 <li class="<?php echo esc_attr( 1 === $step ? 'active' : '' ); ?>">
768 <?php _e( 'Upload CSV file', 'give' ); ?>
769 </li>
770 <li class="<?php echo esc_attr( 2 === $step ? 'active' : '' ); ?>">
771 <?php _e( 'Column mapping', 'give' ); ?>
772 </li>
773 <li class="<?php echo esc_attr( 3 === $step ? 'active' : '' ); ?>">
774 <?php _e( 'Import', 'give' ); ?>
775 </li>
776 <li class="<?php echo esc_attr( 4 === $step ? 'active' : '' ); ?>">
777 <?php _e( 'Done!', 'give' ); ?>
778 </li>
779 </ol>
780 <?php
781 }
782
783 /**
784 * Will return the import step.
785 *
786 * @since 1.8.14
787 *
788 * @return int $step on which step doest the import is on.
789 */
790 public function get_step() {
791 $step = (int) ( isset( $_REQUEST['step'] ) ? give_clean( $_REQUEST['step'] ) : 0 );
792 $on_step = 1;
793
794 if ( empty( $step ) || 1 === $step ) {
795 $on_step = 1;
796 } elseif ( $this->check_for_dropdown_or_import() ) {
797 $on_step = 3;
798 } elseif ( 2 === $step ) {
799 $on_step = 2;
800 } elseif ( 4 === $step ) {
801 $on_step = 4;
802 }
803
804 return $on_step;
805 }
806
807 /**
808 * Render donations import page
809 *
810 * @since 1.8.14
811 */
812 public function render_page() {
813 include_once GIVE_PLUGIN_DIR . 'includes/admin/tools/views/html-admin-page-import-donations.php';
814 }
815
816 /**
817 * Print Dry Run HTML on donation import page
818 *
819 * @since 2.1
820 */
821 public function give_import_donation_submit_button_render_media_csv() {
822 $dry_run = isset( $_POST['dry_run'] ) ? absint( $_POST['dry_run'] ) : 1;
823 ?>
824 <div>
825 <label for="dry_run">
826 <input type="hidden" name="dry_run" value="0"/>
827 <input type="checkbox" name="dry_run" id="dry_run" class="dry_run"
828 value="1" <?php checked( 1, $dry_run ); ?> >
829 <strong><?php _e( 'Dry Run', 'give' ); ?></strong>
830 </label>
831 <p class="give-field-description">
832 <?php
833 _e( 'Preview what the import would look like without making any default changes to your site or your database.', 'give' );
834 ?>
835 </p>
836 </div>
837 <?php
838 }
839
840 /**
841 * Change submit button text on first step of importing donation.
842 *
843 * @since 2.1
844 *
845 * @param $text
846 *
847 * @return string
848 */
849 function give_import_donation_submit_text_render_media_csv( $text ) {
850 return __( 'Begin Import', 'give' );
851 }
852
853 /**
854 * Add CSV upload HTMl
855 *
856 * Print the html of the file upload from which CSV will be uploaded.
857 *
858 * @since 1.8.14
859 * @return void
860 */
861 public function render_media_csv() {
862 add_filter(
863 'give_import_donation_submit_button_text',
864 array(
865 $this,
866 'give_import_donation_submit_text_render_media_csv',
867 )
868 );
869 add_action(
870 'give_import_donation_submit_button',
871 array(
872 $this,
873 'give_import_donation_submit_button_render_media_csv',
874 )
875 );
876 ?>
877 <tr valign="top">
878 <th colspan="2">
879 <h2 id="give-import-title"><?php _e( 'Import donations from a CSV file', 'give' ); ?></h2>
880 <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>
881 </th>
882 </tr>
883 <?php
884 $csv = ( isset( $_POST['csv'] ) ? give_clean( $_POST['csv'] ) : '' );
885 $csv_id = ( isset( $_POST['csv_id'] ) ? give_clean( $_POST['csv_id'] ) : '' );
886 $delimiter = ( isset( $_POST['delimiter'] ) ? give_clean( $_POST['delimiter'] ) : 'csv' );
887 $mode = empty( $_POST['mode'] ) ?
888 'disabled' :
889 ( give_is_setting_enabled( give_clean( $_POST['mode'] ) ) ? 'enabled' : 'disabled' );
890 $create_user = empty( $_POST['create_user'] ) ?
891 'disabled' :
892 ( give_is_setting_enabled( give_clean( $_POST['create_user'] ) ) ? 'enabled' : 'disabled' );
893 $delete_csv = empty( $_POST['delete_csv'] ) ?
894 'enabled' :
895 ( give_is_setting_enabled( give_clean( $_POST['delete_csv'] ) ) ? 'enabled' : 'disabled' );
896
897 // Reset csv and csv_id if csv
898 if ( empty( $csv_id ) || ! $this->is_valid_csv( $csv_id, $csv ) ) {
899 $csv_id = $csv = '';
900 }
901 $per_page = isset( $_POST['per_page'] ) ? absint( $_POST['per_page'] ) : self::$per_page;
902
903 $sample_file_text = sprintf(
904 '%s <a href="%s">%s</a>.',
905 __( 'Download the sample file', 'give' ),
906 esc_url( GIVE_PLUGIN_URL . 'sample-data/sample-data.csv' ),
907 __( 'here', 'give' )
908 );
909
910 $csv_description = sprintf(
911 '%1$s %2$s',
912 __( 'The file must be a Comma Seperated Version (CSV) file type only.', 'give' ),
913 $sample_file_text
914 );
915
916 $settings = array(
917 array(
918 'id' => 'csv',
919 'name' => __( 'Choose a CSV file:', 'give' ),
920 'type' => 'file',
921 'attributes' => array(
922 'editing' => 'false',
923 'library' => 'text',
924 ),
925 'description' => $csv_description,
926 'fvalue' => 'url',
927 'default' => $csv,
928 ),
929 array(
930 'id' => 'csv_id',
931 'type' => 'hidden',
932 'value' => $csv_id,
933 ),
934 array(
935 'id' => 'delimiter',
936 'name' => __( 'CSV Delimiter:', 'give' ),
937 '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' ),
938 'default' => $delimiter,
939 'type' => 'select',
940 'options' => array(
941 'csv' => __( 'Comma', 'give' ),
942 'tab-separated-values' => __( 'Tab', 'give' ),
943 ),
944 ),
945 array(
946 'id' => 'mode',
947 'name' => __( 'Test Mode:', 'give' ),
948 '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' ),
949 'default' => $mode,
950 'type' => 'radio_inline',
951 'options' => array(
952 'enabled' => __( 'Enabled', 'give' ),
953 'disabled' => __( 'Disabled', 'give' ),
954 ),
955 ),
956 array(
957 'id' => 'create_user',
958 'name' => __( 'Create WP users for new donors:', 'give' ),
959 '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' ),
960 'default' => $create_user,
961 'type' => 'radio_inline',
962 'options' => array(
963 'enabled' => __( 'Enabled', 'give' ),
964 'disabled' => __( 'Disabled', 'give' ),
965 ),
966 ),
967 array(
968 'id' => 'delete_csv',
969 'name' => __( 'Delete CSV after import:', 'give' ),
970 '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' ),
971 'default' => $delete_csv,
972 'type' => 'radio_inline',
973 'options' => array(
974 'enabled' => __( 'Enabled', 'give' ),
975 'disabled' => __( 'Disabled', 'give' ),
976 ),
977 ),
978 array(
979 'id' => 'per_page',
980 'name' => __( 'Process Rows Per Batch:', 'give' ),
981 'type' => 'number',
982 'description' => __( 'Determine how many rows you would like to import per cycle.', 'give' ),
983 'default' => $per_page,
984 'class' => 'give-text-small',
985 ),
986 );
987
988 $settings = apply_filters( 'give_import_file_upload_html', $settings );
989
990 if ( empty( $this->is_csv_valid ) ) {
991 Give_Admin_Settings::output_fields( $settings, 'give_settings' );
992 } else {
993 ?>
994 <input type="hidden" name="is_csv_valid" class="is_csv_valid"
995 value="<?php echo esc_attr($this->is_csv_valid); ?>">
996 <?php
997 }
998 }
999
1000 /**
1001 * Run when user click on the submit button.
1002 *
1003 * @since 1.8.14
1004 */
1005 public function save() {
1006 if (!$this->is_nonce_valid()){
1007 wp_die();
1008 }
1009 // Get the current step.
1010 $step = $this->get_step();
1011
1012 // Validation for first step.
1013 if ( 1 === $step ) {
1014 $csv_id = absint( $_POST['csv_id'] );
1015
1016 if ( $this->is_valid_csv( $csv_id, esc_url( $_POST['csv'] ) ) ) {
1017
1018 $url = give_import_page_url(
1019 (array) apply_filters(
1020 'give_import_step_two_url',
1021 array(
1022 'step' => '2',
1023 'importer-type' => $this->importer_type,
1024 'csv' => $csv_id,
1025 'delimiter' => isset( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : 'csv',
1026 'mode' => empty( $_POST['mode'] ) ?
1027 '0' :
1028 ( give_is_setting_enabled( give_clean( $_POST['mode'] ) ) ? '1' : '0' ),
1029 'create_user' => empty( $_POST['create_user'] ) ?
1030 '0' :
1031 ( give_is_setting_enabled( give_clean( $_POST['create_user'] ) ) ? '1' : '0' ),
1032 'delete_csv' => empty( $_POST['delete_csv'] ) ?
1033 '1' :
1034 ( give_is_setting_enabled( give_clean( $_POST['delete_csv'] ) ) ? '1' : '0' ),
1035 'per_page' => isset( $_POST['per_page'] ) ? absint( $_POST['per_page'] ) : self::$per_page,
1036 'dry_run' => isset( $_POST['dry_run'] ) ? absint( $_POST['dry_run'] ) : 0,
1037 )
1038 )
1039 );
1040
1041 $this->is_csv_valid = wp_nonce_url($url, 'give-save-settings', '_give-save-settings');
1042 }
1043 }
1044 }
1045
1046 /**
1047 * Check if user uploaded csv is valid or not.
1048 *
1049 * @since 1.8.14
1050 * @access public
1051 *
1052 * @param mixed $csv ID of the CSV files.
1053 * @param string $match_url ID of the CSV files.
1054 *
1055 * @return bool $has_error CSV is valid or not.
1056 */
1057 private function is_valid_csv( $csv = false, $match_url = '' ) {
1058 $is_valid_csv = true;
1059
1060 if ( $csv ) {
1061 $csv_url = wp_get_attachment_url( $csv );
1062
1063 $delimiter = ( ! empty( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : 'csv' );
1064
1065 if (
1066 ! $csv_url ||
1067 ( ! empty( $match_url ) && ( $csv_url !== $match_url ) ) ||
1068 ( ( $mime_type = get_post_mime_type( $csv ) ) && ! strpos( $mime_type, $delimiter ) )
1069 ) {
1070 $is_valid_csv = false;
1071 Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid CSV file.', 'give' ) );
1072 }
1073 } else {
1074 $is_valid_csv = false;
1075 Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid CSV file.', 'give' ) );
1076 }
1077
1078 return $is_valid_csv;
1079 }
1080
1081
1082 /**
1083 * Render report import field
1084 *
1085 * @since 1.8.14
1086 * @access public
1087 *
1088 * @param $field
1089 * @param $option_value
1090 */
1091 public function render_import_field( $field, $option_value ) {
1092 include_once GIVE_PLUGIN_DIR . 'includes/admin/tools/views/html-admin-page-imports.php';
1093 }
1094
1095 /**
1096 * Get if current page import donations page or not
1097 *
1098 * @since 1.8.14
1099 * @return bool
1100 */
1101 private function is_donations_import_page() {
1102 return 'import' === give_get_current_setting_tab() &&
1103 isset( $_GET['importer-type'] ) &&
1104 $this->importer_type === give_clean( $_GET['importer-type'] );
1105 }
1106
1107 /**
1108 * @since 2.25.2
1109 */
1110 private function is_nonce_valid()
1111 {
1112 return !empty($_REQUEST['_give-save-settings']) && wp_verify_nonce($_REQUEST['_give-save-settings'], 'give-save-settings');
1113 }
1114 }
1115
1116 Give_Import_Donations::get_instance()->setup();
1117 }
1118