PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.7.5
GiveWP – Donation Plugin and Fundraising Platform v2.7.5
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 6 years ago class-give-import-donations.php 6 years ago
class-give-import-donations.php
1101 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 $this->get_step(); ?>"/>
157 <input type="hidden" class="importer-type" value="<?php echo $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 "step-{$step}"; ?> <?php echo( 1 === $step && ! empty( $this->is_csv_valid ) ? 'give-hidden' : '' ); ?> "
175 id="<?php echo "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 "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 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 1.8.14
236 */
237 public function import_success() {
238
239 $delete_csv = ( ! empty( $_GET['delete_csv'] ) ? absint( $_GET['delete_csv'] ) : false );
240 $csv = ( ! empty( $_GET['csv'] ) ? absint( $_GET['csv'] ) : false );
241 if ( ! empty( $delete_csv ) && ! empty( $csv ) ) {
242 wp_delete_attachment( $csv, true );
243 }
244
245 $report = give_import_donation_report();
246
247 $report_html = array(
248 'duplicate_donor' => array(
249 __( '%1$s duplicate %2$s detected', 'give' ),
250 __( '%1$s duplicate %2$s detected', 'give' ),
251 __( 'donor', 'give' ),
252 __( 'donors', 'give' ),
253 ),
254 'create_donor' => array(
255 __( '%1$s %2$s created', 'give' ),
256 __( '%1$s %2$s will be created', 'give' ),
257 __( 'donor', 'give' ),
258 __( 'donors', 'give' ),
259 ),
260 'create_form' => array(
261 __( '%1$s donation %2$s created', 'give' ),
262 __( '%1$s donation %2$s will be created', 'give' ),
263 __( 'form', 'give' ),
264 __( 'forms', 'give' ),
265 ),
266 'duplicate_donation' => array(
267 __( '%1$s duplicate %2$s detected', 'give' ),
268 __( '%1$s duplicate %2$s detected', 'give' ),
269 __( 'donation', 'give' ),
270 __( 'donations', 'give' ),
271 ),
272 'create_donation' => array(
273 __( '%1$s %2$s imported', 'give' ),
274 __( '%1$s %2$s will be imported', 'give' ),
275 __( 'donation', 'give' ),
276 __( 'donations', 'give' ),
277 ),
278 );
279 $total = (int) $_GET['total'];
280 -- $total;
281 $success = (bool) $_GET['success'];
282 $dry_run = empty( $_GET['dry_run'] ) ? 0 : absint( $_GET['dry_run'] );
283 ?>
284 <tr valign="top" class="give-import-dropdown">
285 <th colspan="2">
286 <h2>
287 <?php
288 if ( $success ) {
289 if ( $dry_run ) {
290 printf(
291 _n( 'Dry run import complete! %s donation processed', 'Dry run import complete! %s donations processed', $total, 'give' ),
292 "<strong>{$total}</strong>"
293 );
294 } else {
295 printf(
296 _n( 'Import complete! %s donation processed', 'Import complete! %s donations processed', $total, 'give' ),
297 "<strong>{$total}</strong>"
298 );
299 }
300 } else {
301 printf(
302 _n( 'Failed to import %s donation', 'Failed to import %s donations', $total, 'give' ),
303 "<strong>{$total}</strong>"
304 );
305 }
306 ?>
307 </h2>
308
309 <?php
310 $text = __( 'Import Donation', 'give' );
311 $query_arg = array(
312 'post_type' => 'give_forms',
313 'page' => 'give-tools',
314 'tab' => 'import',
315 );
316 if ( $success ) {
317
318 if ( $dry_run ) {
319 $query_arg = array(
320 'post_type' => 'give_forms',
321 'page' => 'give-tools',
322 'tab' => 'import',
323 'importer-type' => 'import_donations',
324 );
325
326 $text = __( 'Start Import', 'give' );
327 } else {
328 $query_arg = array(
329 'post_type' => 'give_forms',
330 'page' => 'give-payment-history',
331 );
332 $text = __( 'View Donations', 'give' );
333 }
334 }
335
336 foreach ( $report as $key => $value ) {
337 if ( array_key_exists( $key, $report_html ) && ! empty( $value ) ) {
338 $key_name = $report_html[ $key ][2];
339 if ( $value > 1 ) {
340 $key_name = $report_html[ $key ][3];
341 }
342 ?>
343 <p>
344 <?php printf( $report_html[ $key ][ $dry_run ], $value, $key_name ); ?>
345 </p>
346 <?php
347 }
348 }
349 ?>
350
351 <p>
352 <a class="button button-large button-secondary"
353 href="<?php echo add_query_arg( $query_arg, admin_url( 'edit.php' ) ); ?>"><?php echo $text; ?></a>
354 </p>
355 </th>
356 </tr>
357 <?php
358 }
359
360 /**
361 * Will start Import
362 *
363 * @since 1.8.14
364 */
365 public function start_import() {
366 // Reset the donation form report.
367 give_import_donation_report_reset();
368
369 $csv = absint( $_REQUEST['csv'] );
370 $delimiter = ( ! empty( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : 'csv' );
371 $index_start = 1;
372 $next = true;
373 $total = self::get_csv_total( $csv );
374 if ( self::$per_page < $total ) {
375 $total_ajax = ceil( $total / self::$per_page );
376 $index_end = self::$per_page;
377 } else {
378 $total_ajax = 1;
379 $index_end = $total;
380 $next = false;
381 }
382 $current_percentage = 100 / ( $total_ajax + 1 );
383
384 ?>
385 <tr valign="top" class="give-import-dropdown">
386 <th colspan="2">
387 <h2 id="give-import-title"><?php _e( 'Importing', 'give' ); ?></h2>
388 <p class="give-field-description"><?php _e( 'Your donations are now being imported...', 'give' ); ?></p>
389 </th>
390 </tr>
391
392 <tr valign="top" class="give-import-dropdown">
393 <th colspan="2">
394 <span class="spinner is-active"></span>
395 <div class="give-progress"
396 data-current="1"
397 data-total_ajax="<?php echo absint( $total_ajax ); ?>"
398 data-start="<?php echo absint( $index_start ); ?>"
399 data-end="<?php echo absint( $index_end ); ?>"
400 data-next="<?php echo absint( $next ); ?>"
401 data-total="<?php echo absint( $total ); ?>"
402 data-per_page="<?php echo absint( self::$per_page ); ?>">
403
404 <div style="width: <?php echo (float) $current_percentage; ?>%"></div>
405 </div>
406 <input type="hidden" value="3" name="step">
407 <input type="hidden" value='<?php echo esc_attr( maybe_serialize( $_REQUEST['mapto'] ) ); ?>' name="mapto" class="mapto">
408 <input type="hidden" value="<?php echo $csv; ?>" name="csv" class="csv">
409 <input type="hidden" value="<?php echo esc_attr( $_REQUEST['mode'] ); ?>" name="mode" class="mode">
410 <input type="hidden" value="<?php echo esc_attr( $_REQUEST['create_user'] ); ?>" name="create_user" class="create_user">
411 <input type="hidden" value="<?php echo esc_attr( $_REQUEST['delete_csv'] ); ?>" name="delete_csv" class="delete_csv">
412 <input type="hidden" value="<?php echo esc_attr( $delimiter ); ?>" name="delimiter">
413 <input type="hidden" value="<?php echo absint( $_REQUEST['dry_run'] ); ?>" name="dry_run">
414 <input type="hidden" value='<?php echo esc_attr( maybe_serialize( self::get_importer( $csv, 0, $delimiter ) ) ); ?>' name="main_key" class="main_key">
415 </th>
416 </tr>
417 <?php
418 }
419
420 /**
421 * Will return true if importing can be started or not else false.
422 *
423 * @since 1.8.14
424 */
425 public function check_for_dropdown_or_import() {
426 $return = true;
427 if ( isset( $_REQUEST['mapto'] ) ) {
428 $mapto = (array) $_REQUEST['mapto'];
429 if ( false === in_array( 'form_title', $mapto ) && false === in_array( 'form_id', $mapto ) ) {
430 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' ) );
431 $return = false;
432 }
433
434 if ( false === in_array( 'amount', $mapto ) ) {
435 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' ) );
436 $return = false;
437 }
438
439 if ( false === in_array( 'email', $mapto ) && false === in_array( 'donor_id', $mapto ) ) {
440 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' ) );
441 $return = false;
442 }
443 } else {
444 $return = false;
445 }
446
447 return $return;
448 }
449
450 /**
451 * Print the Dropdown option for CSV.
452 *
453 * @since 1.8.14
454 */
455 public function render_dropdown() {
456 $csv = (int) $_GET['csv'];
457 $delimiter = ( ! empty( $_GET['delimiter'] ) ? give_clean( $_GET['delimiter'] ) : 'csv' );
458
459 // TO check if the CSV files that is being add is valid or not if not then redirect to first step again
460 if ( ! $this->is_valid_csv( $csv ) ) {
461 $url = give_import_page_url();
462 ?>
463 <input type="hidden" name="csv_not_valid" class="csv_not_valid" value="<?php echo $url; ?>"/>
464 <?php
465 } else {
466 ?>
467 <tr valign="top" class="give-import-dropdown">
468 <th colspan="2">
469 <h2 id="give-import-title"><?php _e( 'Map CSV fields to donations', 'give' ); ?></h2>
470
471 <p class="give-import-donation-required-fields-title"><?php _e( 'Required Fields' ); ?></p>
472
473 <p class="give-field-description"><?php _e( 'These fields are required for the import to submitted' ); ?></p>
474
475 <ul class="give-import-donation-required-fields">
476 <li class="give-import-donation-required-email"
477 title="Please configure all required fields to start the import process.">
478 <span class="give-import-donation-required-symbol dashicons dashicons-no-alt"></span>
479 <span class="give-import-donation-required-text">
480 <?php
481 _e( 'Email Address', 'give' );
482 ?>
483 </span>
484 </li>
485
486 <li class="give-import-donation-required-first"
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( 'First Name', 'give' );
492 ?>
493 </span>
494 </li>
495
496 <li class="give-import-donation-required-amount"
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( 'Donation Amount', 'give' );
502 ?>
503 </span>
504 </li>
505
506 <li class="give-import-donation-required-form"
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( 'Form Title or ID', 'give' );
512 ?>
513 </span>
514 </li>
515 </ul>
516
517 <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>
518 </th>
519 </tr>
520
521 <tr valign="top" class="give-import-dropdown">
522 <th><b><?php _e( 'Column name', 'give' ); ?></b></th>
523 <th><b><?php _e( 'Map to field', 'give' ); ?></b></th>
524 </tr>
525
526 <?php
527 $raw_key = $this->get_importer( $csv, 0, $delimiter );
528 $mapto = (array) ( isset( $_REQUEST['mapto'] ) ? $_REQUEST['mapto'] : array() );
529
530 foreach ( $raw_key as $index => $value ) {
531 ?>
532 <tr valign="middle" class="give-import-option">
533 <th><?php echo $value; ?></th>
534 <th>
535 <?php
536 $this->get_columns( $index, $value, $mapto );
537 ?>
538 </th>
539 </tr>
540 <?php
541 }
542 }
543 }
544
545 /**
546 * @param $option_value
547 * @param $value
548 *
549 * @return string
550 */
551 public function selected( $option_value, $value ) {
552 $option_value = strtolower( $option_value );
553 $value = strtolower( $value );
554
555 $selected = '';
556 if ( stristr( $value, $option_value ) ) {
557 $selected = 'selected';
558 } elseif ( strrpos( $value, 'give_' ) && stristr( $option_value, __( 'Import as Meta', 'give' ) ) ) {
559 $selected = 'selected';
560 }
561
562 return $selected;
563 }
564
565 /**
566 * Print the columns from the CSV.
567 *
568 * @since 1.8.14
569 * @access private
570 *
571 * @param string $index
572 * @param bool $value
573 * @param array $mapto
574 *
575 * @return void
576 */
577 private function get_columns( $index, $value = false, $mapto = array() ) {
578 $default = give_import_default_options();
579 $current_mapto = (string) ( ! empty( $mapto[ $index ] ) ? $mapto[ $index ] : '' );
580 ?>
581 <select name="mapto[<?php echo $index; ?>]">
582 <?php $this->get_dropdown_option_html( $default, $current_mapto, $value ); ?>
583
584 <optgroup label="<?php _e( 'Donations', 'give' ); ?>">
585 <?php
586 $this->get_dropdown_option_html( give_import_donations_options(), $current_mapto, $value );
587 ?>
588 </optgroup>
589
590 <optgroup label="<?php _e( 'Donors', 'give' ); ?>">
591 <?php
592 $this->get_dropdown_option_html( give_import_donor_options(), $current_mapto, $value );
593 ?>
594 </optgroup>
595
596 <optgroup label="<?php _e( 'Forms', 'give' ); ?>">
597 <?php
598 $this->get_dropdown_option_html( give_import_donation_form_options(), $current_mapto, $value );
599 ?>
600 </optgroup>
601
602 <?php
603 /**
604 * Fire the action
605 * You can use this filter to add new options.
606 *
607 * @since 1.8.15
608 */
609 do_action( 'give_import_dropdown_option', $index, $value, $mapto, $current_mapto );
610 ?>
611 </select>
612 <?php
613 }
614
615 /**
616 * Print the option html for select in importer
617 *
618 * @since 1.8.15
619 * @access public
620 *
621 * @param array $options
622 * @param string $current_mapto
623 * @param bool $value
624 *
625 * @return void
626 */
627 public function get_dropdown_option_html( $options, $current_mapto, $value = false ) {
628
629 foreach ( $options as $option => $option_value ) {
630 $ignore = array();
631 if ( isset( $option_value['ignore'] ) && is_array( $option_value['ignore'] ) ) {
632 $ignore = $option_value['ignore'];
633 unset( $option_value['ignore'] );
634 }
635
636 $option_value_texts = (array) $option_value;
637 $option_text = $option_value_texts[0];
638
639 $checked = ( ( $current_mapto === $option ) ? 'selected' : false );
640 if ( empty( $checked ) && ! in_array( $value, $ignore ) ) {
641 foreach ( $option_value_texts as $option_value_text ) {
642 $checked = $this->selected( $option_value_text, $value );
643 if ( $checked ) {
644 break;
645 }
646 }
647 }
648
649 echo sprintf(
650 '<option value="%1$s" %2$s >%3$s</option>',
651 $option,
652 $checked,
653 $option_text
654 );
655 }
656 }
657
658 /**
659 * Get column count of csv file.
660 *
661 * @since 1.8.14
662 *
663 * @param $file_id
664 *
665 * @return bool|int
666 */
667 public function get_csv_total( $file_id ) {
668 $total = false;
669 if ( $file_id ) {
670 $file_dir = get_attached_file( $file_id );
671 if ( $file_dir ) {
672 $total = $this->get_csv_data_from_file_dir( $file_dir );
673 }
674 }
675
676 return $total;
677 }
678
679 /**
680 * Get data from File
681 *
682 * @since 2.1
683 *
684 * @param $file_dir
685 *
686 * @return bool|int
687 */
688 public function get_csv_data_from_file_dir( $file_dir ) {
689 $total = false;
690 if ( $file_dir ) {
691 $file = new SplFileObject( $file_dir, 'r' );
692 $file->seek( PHP_INT_MAX );
693 $total = $file->key() + 1;
694 }
695
696 return $total;
697 }
698
699 /**
700 * Get the CSV fields title from the CSV.
701 *
702 * @since 1.8.14
703 *
704 * @param (int) $file_id
705 * @param int $index
706 * @param string $delimiter
707 *
708 * @return array|bool $raw_data title of the CSV file fields
709 */
710 public function get_importer( $file_id, $index = 0, $delimiter = 'csv' ) {
711 /**
712 * Filter to modify delimiter of Import.
713 *
714 * @since 1.8.14
715 *
716 * Return string $delimiter.
717 */
718 $delimiter = (string) apply_filters( 'give_import_delimiter_set', $delimiter );
719
720 $raw_data = false;
721 $file_dir = get_attached_file( $file_id );
722 if ( $file_dir ) {
723 if ( false !== ( $handle = fopen( $file_dir, 'r' ) ) ) {
724 $raw_data = fgetcsv( $handle, $index, $delimiter );
725 // Remove BOM signature from the first item.
726 if ( isset( $raw_data[0] ) ) {
727 $raw_data[0] = $this->remove_utf8_bom( $raw_data[0] );
728 }
729 }
730 }
731
732 return $raw_data;
733 }
734
735 /**
736 * Remove UTF-8 BOM signature.
737 *
738 * @since 1.8.14
739 *
740 * @param string $string String to handle.
741 *
742 * @return string
743 */
744 public function remove_utf8_bom( $string ) {
745 if ( 'efbbbf' === substr( bin2hex( $string ), 0, 6 ) ) {
746 $string = substr( $string, 3 );
747 }
748
749 return $string;
750 }
751
752 /**
753 * Is used to show the process when user upload the donor form.
754 *
755 * @since 1.8.14
756 */
757 public function render_progress() {
758 $step = $this->get_step();
759 ?>
760 <ol class="give-progress-steps">
761 <li class="<?php echo( 1 === $step ? 'active' : '' ); ?>">
762 <?php _e( 'Upload CSV file', 'give' ); ?>
763 </li>
764 <li class="<?php echo( 2 === $step ? 'active' : '' ); ?>">
765 <?php _e( 'Column mapping', 'give' ); ?>
766 </li>
767 <li class="<?php echo( 3 === $step ? 'active' : '' ); ?>">
768 <?php _e( 'Import', 'give' ); ?>
769 </li>
770 <li class="<?php echo( 4 === $step ? 'active' : '' ); ?>">
771 <?php _e( 'Done!', 'give' ); ?>
772 </li>
773 </ol>
774 <?php
775 }
776
777 /**
778 * Will return the import step.
779 *
780 * @since 1.8.14
781 *
782 * @return int $step on which step doest the import is on.
783 */
784 public function get_step() {
785 $step = (int) ( isset( $_REQUEST['step'] ) ? give_clean( $_REQUEST['step'] ) : 0 );
786 $on_step = 1;
787
788 if ( empty( $step ) || 1 === $step ) {
789 $on_step = 1;
790 } elseif ( $this->check_for_dropdown_or_import() ) {
791 $on_step = 3;
792 } elseif ( 2 === $step ) {
793 $on_step = 2;
794 } elseif ( 4 === $step ) {
795 $on_step = 4;
796 }
797
798 return $on_step;
799 }
800
801 /**
802 * Render donations import page
803 *
804 * @since 1.8.14
805 */
806 public function render_page() {
807 include_once GIVE_PLUGIN_DIR . 'includes/admin/tools/views/html-admin-page-import-donations.php';
808 }
809
810 /**
811 * Print Dry Run HTML on donation import page
812 *
813 * @since 2.1
814 */
815 public function give_import_donation_submit_button_render_media_csv() {
816 $dry_run = isset( $_POST['dry_run'] ) ? absint( $_POST['dry_run'] ) : 1;
817 ?>
818 <div>
819 <label for="dry_run">
820 <input type="hidden" name="dry_run" value="0"/>
821 <input type="checkbox" name="dry_run" id="dry_run" class="dry_run"
822 value="1" <?php checked( 1, $dry_run ); ?> >
823 <strong><?php _e( 'Dry Run', 'give' ); ?></strong>
824 </label>
825 <p class="give-field-description">
826 <?php
827 _e( 'Preview what the import would look like without making any default changes to your site or your database.', 'give' );
828 ?>
829 </p>
830 </div>
831 <?php
832 }
833
834 /**
835 * Change submit button text on first step of importing donation.
836 *
837 * @since 2.1
838 *
839 * @param $text
840 *
841 * @return string
842 */
843 function give_import_donation_submit_text_render_media_csv( $text ) {
844 return __( 'Begin Import', 'give' );
845 }
846
847 /**
848 * Add CSV upload HTMl
849 *
850 * Print the html of the file upload from which CSV will be uploaded.
851 *
852 * @since 1.8.14
853 * @return void
854 */
855 public function render_media_csv() {
856 add_filter(
857 'give_import_donation_submit_button_text',
858 array(
859 $this,
860 'give_import_donation_submit_text_render_media_csv',
861 )
862 );
863 add_action(
864 'give_import_donation_submit_button',
865 array(
866 $this,
867 'give_import_donation_submit_button_render_media_csv',
868 )
869 );
870 ?>
871 <tr valign="top">
872 <th colspan="2">
873 <h2 id="give-import-title"><?php _e( 'Import donations from a CSV file', 'give' ); ?></h2>
874 <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>
875 </th>
876 </tr>
877 <?php
878 $csv = ( isset( $_POST['csv'] ) ? give_clean( $_POST['csv'] ) : '' );
879 $csv_id = ( isset( $_POST['csv_id'] ) ? give_clean( $_POST['csv_id'] ) : '' );
880 $delimiter = ( isset( $_POST['delimiter'] ) ? give_clean( $_POST['delimiter'] ) : 'csv' );
881 $mode = empty( $_POST['mode'] ) ?
882 'disabled' :
883 ( give_is_setting_enabled( give_clean( $_POST['mode'] ) ) ? 'enabled' : 'disabled' );
884 $create_user = empty( $_POST['create_user'] ) ?
885 'disabled' :
886 ( give_is_setting_enabled( give_clean( $_POST['create_user'] ) ) ? 'enabled' : 'disabled' );
887 $delete_csv = empty( $_POST['delete_csv'] ) ?
888 'enabled' :
889 ( give_is_setting_enabled( give_clean( $_POST['delete_csv'] ) ) ? 'enabled' : 'disabled' );
890
891 // Reset csv and csv_id if csv
892 if ( empty( $csv_id ) || ! $this->is_valid_csv( $csv_id, $csv ) ) {
893 $csv_id = $csv = '';
894 }
895 $per_page = isset( $_POST['per_page'] ) ? absint( $_POST['per_page'] ) : self::$per_page;
896
897 $sample_file_text = sprintf(
898 '%s <a href="%s">%s</a>.',
899 __( 'Download the sample file', 'give' ),
900 esc_url( GIVE_PLUGIN_URL . 'sample-data/sample-data.csv' ),
901 __( 'here', 'give' )
902 );
903
904 $csv_description = sprintf(
905 '%1$s %2$s',
906 __( 'The file must be a Comma Seperated Version (CSV) file type only.', 'give' ),
907 $sample_file_text
908 );
909
910 $settings = array(
911 array(
912 'id' => 'csv',
913 'name' => __( 'Choose a CSV file:', 'give' ),
914 'type' => 'file',
915 'attributes' => array(
916 'editing' => 'false',
917 'library' => 'text',
918 ),
919 'description' => $csv_description,
920 'fvalue' => 'url',
921 'default' => $csv,
922 ),
923 array(
924 'id' => 'csv_id',
925 'type' => 'hidden',
926 'value' => $csv_id,
927 ),
928 array(
929 'id' => 'delimiter',
930 'name' => __( 'CSV Delimiter:', 'give' ),
931 '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' ),
932 'default' => $delimiter,
933 'type' => 'select',
934 'options' => array(
935 'csv' => __( 'Comma', 'give' ),
936 'tab-separated-values' => __( 'Tab', 'give' ),
937 ),
938 ),
939 array(
940 'id' => 'mode',
941 'name' => __( 'Test Mode:', 'give' ),
942 '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' ),
943 'default' => $mode,
944 'type' => 'radio_inline',
945 'options' => array(
946 'enabled' => __( 'Enabled', 'give' ),
947 'disabled' => __( 'Disabled', 'give' ),
948 ),
949 ),
950 array(
951 'id' => 'create_user',
952 'name' => __( 'Create WP users for new donors:', 'give' ),
953 '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' ),
954 'default' => $create_user,
955 'type' => 'radio_inline',
956 'options' => array(
957 'enabled' => __( 'Enabled', 'give' ),
958 'disabled' => __( 'Disabled', 'give' ),
959 ),
960 ),
961 array(
962 'id' => 'delete_csv',
963 'name' => __( 'Delete CSV after import:', 'give' ),
964 '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' ),
965 'default' => $delete_csv,
966 'type' => 'radio_inline',
967 'options' => array(
968 'enabled' => __( 'Enabled', 'give' ),
969 'disabled' => __( 'Disabled', 'give' ),
970 ),
971 ),
972 array(
973 'id' => 'per_page',
974 'name' => __( 'Process Rows Per Batch:', 'give' ),
975 'type' => 'number',
976 'description' => __( 'Determine how many rows you would like to import per cycle.', 'give' ),
977 'default' => $per_page,
978 'class' => 'give-text-small',
979 ),
980 );
981
982 $settings = apply_filters( 'give_import_file_upload_html', $settings );
983
984 if ( empty( $this->is_csv_valid ) ) {
985 Give_Admin_Settings::output_fields( $settings, 'give_settings' );
986 } else {
987 ?>
988 <input type="hidden" name="is_csv_valid" class="is_csv_valid"
989 value="<?php echo $this->is_csv_valid; ?>">
990 <?php
991 }
992 }
993
994 /**
995 * Run when user click on the submit button.
996 *
997 * @since 1.8.14
998 */
999 public function save() {
1000 // Get the current step.
1001 $step = $this->get_step();
1002
1003 // Validation for first step.
1004 if ( 1 === $step ) {
1005 $csv_id = absint( $_POST['csv_id'] );
1006
1007 if ( $this->is_valid_csv( $csv_id, esc_url( $_POST['csv'] ) ) ) {
1008
1009 $url = give_import_page_url(
1010 (array) apply_filters(
1011 'give_import_step_two_url',
1012 array(
1013 'step' => '2',
1014 'importer-type' => $this->importer_type,
1015 'csv' => $csv_id,
1016 'delimiter' => isset( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : 'csv',
1017 'mode' => empty( $_POST['mode'] ) ?
1018 '0' :
1019 ( give_is_setting_enabled( give_clean( $_POST['mode'] ) ) ? '1' : '0' ),
1020 'create_user' => empty( $_POST['create_user'] ) ?
1021 '0' :
1022 ( give_is_setting_enabled( give_clean( $_POST['create_user'] ) ) ? '1' : '0' ),
1023 'delete_csv' => empty( $_POST['delete_csv'] ) ?
1024 '1' :
1025 ( give_is_setting_enabled( give_clean( $_POST['delete_csv'] ) ) ? '1' : '0' ),
1026 'per_page' => isset( $_POST['per_page'] ) ? absint( $_POST['per_page'] ) : self::$per_page,
1027 'dry_run' => isset( $_POST['dry_run'] ) ? absint( $_POST['dry_run'] ) : 0,
1028 )
1029 )
1030 );
1031
1032 $this->is_csv_valid = $url;
1033 }
1034 }
1035 }
1036
1037 /**
1038 * Check if user uploaded csv is valid or not.
1039 *
1040 * @since 1.8.14
1041 * @access public
1042 *
1043 * @param mixed $csv ID of the CSV files.
1044 * @param string $match_url ID of the CSV files.
1045 *
1046 * @return bool $has_error CSV is valid or not.
1047 */
1048 private function is_valid_csv( $csv = false, $match_url = '' ) {
1049 $is_valid_csv = true;
1050
1051 if ( $csv ) {
1052 $csv_url = wp_get_attachment_url( $csv );
1053
1054 $delimiter = ( ! empty( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : 'csv' );
1055
1056 if (
1057 ! $csv_url ||
1058 ( ! empty( $match_url ) && ( $csv_url !== $match_url ) ) ||
1059 ( ( $mime_type = get_post_mime_type( $csv ) ) && ! strpos( $mime_type, $delimiter ) )
1060 ) {
1061 $is_valid_csv = false;
1062 Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid CSV file.', 'give' ) );
1063 }
1064 } else {
1065 $is_valid_csv = false;
1066 Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid CSV file.', 'give' ) );
1067 }
1068
1069 return $is_valid_csv;
1070 }
1071
1072
1073 /**
1074 * Render report import field
1075 *
1076 * @since 1.8.14
1077 * @access public
1078 *
1079 * @param $field
1080 * @param $option_value
1081 */
1082 public function render_import_field( $field, $option_value ) {
1083 include_once GIVE_PLUGIN_DIR . 'includes/admin/tools/views/html-admin-page-imports.php';
1084 }
1085
1086 /**
1087 * Get if current page import donations page or not
1088 *
1089 * @since 1.8.14
1090 * @return bool
1091 */
1092 private function is_donations_import_page() {
1093 return 'import' === give_get_current_setting_tab() &&
1094 isset( $_GET['importer-type'] ) &&
1095 $this->importer_type === give_clean( $_GET['importer-type'] );
1096 }
1097 }
1098
1099 Give_Import_Donations::get_instance()->setup();
1100 }
1101