PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.2.5
GiveWP – Donation Plugin and Fundraising Platform v2.2.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 7 years ago class-give-import-donations.php 7 years ago
class-give-import-donations.php
1096 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, WordImpress
10 * @license https://opensource.org/licenses/gpl-license GNU Public License
11 * @since 1.8.14
12 */
13
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit; // Exit if accessed directly
16 }
17
18 if ( ! class_exists( 'Give_Import_Donations' ) ) {
19
20 /**
21 * Give_Import_Donations.
22 *
23 * @since 1.8.14
24 */
25 final class Give_Import_Donations {
26
27 /**
28 * Importer type
29 *
30 * @since 1.8.13
31 * @var string
32 */
33 private $importer_type = 'import_donations';
34
35 /**
36 * Instance.
37 *
38 * @since
39 * @access private
40 * @var
41 */
42 static private $instance;
43
44 /**
45 * Importing donation per page.
46 *
47 * @since 1.8.14
48 *
49 * @var int
50 */
51 public static $per_page = 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
116 // Render donation import page
117 add_action( 'give_admin_field_tools_import', array( $this, 'render_page' ) );
118
119 // Print the HTML.
120 add_action( 'give_tools_import_donations_form_start', array( $this, 'html' ), 10 );
121
122 // Run when form submit.
123 add_action( 'give-tools_save_import', array( $this, 'save' ) );
124
125 add_action( 'give-tools_update_notices', array( $this, 'update_notices' ), 11, 1 );
126
127 // Used to add submit button.
128 add_action( 'give_tools_import_donations_form_end', array( $this, 'submit' ), 10 );
129 }
130
131 /**
132 * Update notice
133 *
134 * @since 1.8.14
135 *
136 * @param $messages
137 *
138 * @return mixed
139 */
140 public function update_notices( $messages ) {
141 if ( ! empty( $_GET['tab'] ) && 'import' === give_clean( $_GET['tab'] ) ) {
142 unset( $messages['give-setting-updated'] );
143 }
144
145 return $messages;
146 }
147
148 /**
149 * Print submit and nonce button.
150 *
151 * @since 1.8.14
152 */
153 public function submit() {
154 wp_nonce_field( 'give-save-settings', '_give-save-settings' );
155 ?>
156 <input type="hidden" class="import-step" id="import-step" name="step"
157 value="<?php echo $this->get_step(); ?>"/>
158 <input type="hidden" class="importer-type" value="<?php echo $this->importer_type; ?>"/>
159 <?php
160 }
161
162 /**
163 * Print the HTML for importer.
164 *
165 * @since 1.8.14
166 */
167 public function html() {
168 $step = $this->get_step();
169
170 // Show progress.
171 $this->render_progress();
172 ?>
173 <section>
174 <table
175 class="widefat export-options-table give-table <?php echo "step-{$step}"; ?> <?php echo( 1 === $step && ! empty( $this->is_csv_valid ) ? 'give-hidden' : '' ); ?> "
176 id="<?php echo "step-{$step}"; ?>">
177 <tbody>
178 <?php
179 switch ( $step ) {
180 case 1:
181 $this->render_media_csv();
182 break;
183
184 case 2:
185 $this->render_dropdown();
186 break;
187
188 case 3:
189 $this->start_import();
190 break;
191
192 case 4:
193 $this->import_success();
194 }
195 if ( false === $this->check_for_dropdown_or_import() ) {
196 ?>
197 <tr valign="top">
198 <th>
199 <input type="submit"
200 class="button button-primary button-large button-secondary <?php echo "step-{$step}"; ?>"
201 id="recount-stats-submit"
202 value="
203 <?php
204 /**
205 * Filter to modify donation importer submit button text.
206 *
207 * @since 2.1
208 */
209 echo apply_filters( 'give_import_donation_submit_button_text', __( 'Submit', 'give' ) );
210 ?>
211 "/>
212 </th>
213 <th>
214 <?php
215 /**
216 * Action to add submit button description.
217 *
218 * @since 2.1
219 */
220 do_action( 'give_import_donation_submit_button' );
221 ?>
222 </th>
223 </tr>
224 <?php
225 }
226 ?>
227 </tbody>
228 </table>
229 </section>
230 <?php
231 }
232
233 /**
234 * Show success notice
235 *
236 * @since 1.8.14
237 */
238 public function import_success() {
239
240 $delete_csv = ( ! empty( $_GET['delete_csv'] ) ? absint( $_GET['delete_csv'] ) : false );
241 $csv = ( ! empty( $_GET['csv'] ) ? absint( $_GET['csv'] ) : false );
242 if ( ! empty( $delete_csv ) && ! empty( $csv ) ) {
243 wp_delete_attachment( $csv, true );
244 }
245
246 $report = give_import_donation_report();
247
248 $report_html = array(
249 'duplicate_donor' => array(
250 __( '%s duplicate %s detected', 'give' ),
251 __( '%s duplicate %s will be detected', 'give' ),
252 __( 'donor', 'give' ),
253 __( 'donors', 'give' ),
254 ),
255 'create_donor' => array(
256 __( '%s %s created', 'give' ),
257 __( '%s %s will be going to get created', 'give' ),
258 __( 'donor', 'give' ),
259 __( 'donors', 'give' ),
260 ),
261 'create_form' => array(
262 __( '%s donation %s created', 'give' ),
263 __( '%s donation %s will be going to get created', 'give' ),
264 __( 'form', 'give' ),
265 __( 'forms', 'give' ),
266 ),
267 'duplicate_donation' => array(
268 __( '%s duplicate %s detected', 'give' ),
269 __( '%s duplicate %s will be detected', 'give' ),
270 __( 'donation', 'give' ),
271 __( 'donations', 'give' ),
272 ),
273 'create_donation' => array(
274 __( '%s %s imported', 'give' ),
275 __( '%s %s will going to get imported', 'give' ),
276 __( 'donation', 'give' ),
277 __( 'donations', 'give' ),
278 ),
279 );
280 $total = (int) $_GET['total'];
281 -- $total;
282 $success = (bool) $_GET['success'];
283 $dry_run = empty( $_GET['dry_run'] ) ? 0 : absint( $_GET['dry_run'] );
284 ?>
285 <tr valign="top" class="give-import-dropdown">
286 <th colspan="2">
287 <h2>
288 <?php
289 if ( $success ) {
290 if ( $dry_run ) {
291 printf(
292 _n( 'Dry run import complete! %s donation processed', 'Dry run import complete! %s donations processed', $total, 'give' ),
293 "<strong>{$total}</strong>"
294 );
295 } else {
296 printf(
297 _n( 'Import complete! %s donation processed', 'Import complete! %s donations processed', $total, 'give' ),
298 "<strong>{$total}</strong>"
299 );
300 }
301 } else {
302 printf(
303 _n( 'Failed to import %s donation', 'Failed to import %s donations', $total, 'give' ),
304 "<strong>{$total}</strong>"
305 );
306 }
307 ?>
308 </h2>
309
310 <?php
311 $text = __( 'Import Donation', 'give' );
312 $query_arg = array(
313 'post_type' => 'give_forms',
314 'page' => 'give-tools',
315 'tab' => 'import',
316 );
317 if ( $success ) {
318
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 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 = (int) $_REQUEST['csv'];
372 $delimiter = ( ! empty( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : 'csv' );
373 $index_start = 1;
374 $index_end = 1;
375 $next = true;
376 $total = self::get_csv_total( $csv );
377 if ( self::$per_page < $total ) {
378 $total_ajax = ceil( $total / self::$per_page );
379 $index_end = self::$per_page;
380 } else {
381 $total_ajax = 1;
382 $index_end = $total;
383 $next = false;
384 }
385 $current_percentage = 100 / ( $total_ajax + 1 );
386
387 ?>
388 <tr valign="top" class="give-import-dropdown">
389 <th colspan="2">
390 <h2 id="give-import-title"><?php _e( 'Importing', 'give' ) ?></h2>
391 <p class="give-field-description"><?php _e( 'Your donations are now being imported...', 'give' ) ?></p>
392 </th>
393 </tr>
394
395 <tr valign="top" class="give-import-dropdown">
396 <th colspan="2">
397 <span class="spinner is-active"></span>
398 <div class="give-progress"
399 data-current="1"
400 data-total_ajax="<?php echo $total_ajax; ?>"
401 data-start="<?php echo $index_start; ?>"
402 data-end="<?php echo $index_end; ?>"
403 data-next="<?php echo $next; ?>"
404 data-total="<?php echo $total; ?>"
405 data-per_page="<?php echo self::$per_page; ?>">
406
407 <div style="width: <?php echo $current_percentage; ?>%"></div>
408 </div>
409 <input type="hidden" value="3" name="step">
410 <input type="hidden" value='<?php echo maybe_serialize( $_REQUEST['mapto'] ); ?>' name="mapto"
411 class="mapto">
412 <input type="hidden" value="<?php echo $_REQUEST['csv']; ?>" name="csv" class="csv">
413 <input type="hidden" value="<?php echo $_REQUEST['mode']; ?>" name="mode" class="mode">
414 <input type="hidden" value="<?php echo $_REQUEST['create_user']; ?>" name="create_user"
415 class="create_user">
416 <input type="hidden" value="<?php echo $_REQUEST['delete_csv']; ?>" name="delete_csv"
417 class="delete_csv">
418 <input type="hidden" value="<?php echo $delimiter; ?>" name="delimiter">
419 <input type="hidden" value="<?php echo absint( $_REQUEST['dry_run'] ); ?>" name="dry_run">
420 <input type="hidden"
421 value='<?php echo maybe_serialize( self::get_importer( $csv, 0, $delimiter ) ); ?>'
422 name="main_key"
423 class="main_key">
424 </th>
425 </tr>
426 <?php
427 }
428
429 /**
430 * Will return true if importing can be started or not else false.
431 *
432 * @since 1.8.14
433 */
434 public function check_for_dropdown_or_import() {
435 $return = true;
436 if ( isset( $_REQUEST['mapto'] ) ) {
437 $mapto = (array) $_REQUEST['mapto'];
438 if ( false === in_array( 'form_title', $mapto ) && false === in_array( 'form_id', $mapto ) ) {
439 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' ) );
440 $return = false;
441 }
442
443 if ( false === in_array( 'amount', $mapto ) ) {
444 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' ) );
445 $return = false;
446 }
447
448 if ( false === in_array( 'email', $mapto ) && false === in_array( 'donor_id', $mapto ) ) {
449 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' ) );
450 $return = false;
451 }
452 } else {
453 $return = false;
454 }
455
456 return $return;
457 }
458
459 /**
460 * Print the Dropdown option for CSV.
461 *
462 * @since 1.8.14
463 */
464 public function render_dropdown() {
465 $csv = (int) $_GET['csv'];
466 $delimiter = ( ! empty( $_GET['delimiter'] ) ? give_clean( $_GET['delimiter'] ) : 'csv' );
467
468 // TO check if the CSV files that is being add is valid or not if not then redirect to first step again
469 if ( ! $this->is_valid_csv( $csv ) ) {
470 $url = give_import_page_url();
471 ?>
472 <input type="hidden" name="csv_not_valid" class="csv_not_valid" value="<?php echo $url; ?>"/>
473 <?php
474 } else {
475 ?>
476 <tr valign="top" class="give-import-dropdown">
477 <th colspan="2">
478 <h2 id="give-import-title"><?php _e( 'Map CSV fields to donations', 'give' ) ?></h2>
479
480 <p class="give-import-donation-required-fields-title"><?php _e( 'Required Fields' ); ?></p>
481
482 <p class="give-field-description"><?php _e( 'These fields are required for the import to submitted' ); ?></p>
483
484 <ul class="give-import-donation-required-fields">
485 <li class="give-import-donation-required-email"
486 title="Please configure all required fields to start the import process.">
487 <span class="give-import-donation-required-symbol dashicons dashicons-no-alt"></span>
488 <span class="give-import-donation-required-text">
489 <?php
490 _e( 'Email Address', 'give' );
491 ?>
492 </span>
493 </li>
494
495 <li class="give-import-donation-required-first"
496 title="Please configure all required fields to start the import process.">
497 <span class="give-import-donation-required-symbol dashicons dashicons-no-alt"></span>
498 <span class="give-import-donation-required-text">
499 <?php
500 _e( 'First Name', 'give' );
501 ?>
502 </span>
503 </li>
504
505 <li class="give-import-donation-required-amount"
506 title="Please configure all required fields to start the import process.">
507 <span class="give-import-donation-required-symbol dashicons dashicons-no-alt"></span>
508 <span class="give-import-donation-required-text">
509 <?php
510 _e( 'Donation Amount', 'give' );
511 ?>
512 </span>
513 </li>
514
515 <li class="give-import-donation-required-form"
516 title="Please configure all required fields to start the import process.">
517 <span class="give-import-donation-required-symbol dashicons dashicons-no-alt"></span>
518 <span class="give-import-donation-required-text">
519 <?php
520 _e( 'Form Title or ID', 'give' );
521 ?>
522 </span>
523 </li>
524 </ul>
525
526 <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>
527 </th>
528 </tr>
529
530 <tr valign="top" class="give-import-dropdown">
531 <th><b><?php _e( 'Column name', 'give' ); ?></b></th>
532 <th><b><?php _e( 'Map to field', 'give' ); ?></b></th>
533 </tr>
534
535 <?php
536 $raw_key = $this->get_importer( $csv, 0, $delimiter );
537 $mapto = (array) ( isset( $_REQUEST['mapto'] ) ? $_REQUEST['mapto'] : array() );
538
539 foreach ( $raw_key as $index => $value ) {
540 ?>
541 <tr valign="top" class="give-import-option">
542 <th><?php echo $value; ?></th>
543 <th>
544 <?php
545 $this->get_columns( $index, $value, $mapto );
546 ?>
547 </th>
548 </tr>
549 <?php
550 }
551 }
552 }
553
554 /**
555 * @param $option_value
556 * @param $value
557 *
558 * @return string
559 */
560 public function selected( $option_value, $value ) {
561 $option_value = strtolower( $option_value );
562 $value = strtolower( $value );
563
564 $selected = '';
565 if ( stristr( $value, $option_value ) ) {
566 $selected = 'selected';
567 } elseif ( strrpos( $value, 'give_' ) && stristr( $option_value, __( 'Import as Meta', 'give' ) ) ) {
568 $selected = 'selected';
569 }
570
571 return $selected;
572 }
573
574 /**
575 * Print the columns from the CSV.
576 *
577 * @since 1.8.14
578 * @access private
579 *
580 * @param string $index
581 * @param bool $value
582 * @param array $mapto
583 *
584 * @return void
585 */
586 private function get_columns( $index, $value = false, $mapto = array() ) {
587 $default = give_import_default_options();
588 $current_mapto = (string) ( ! empty( $mapto[ $index ] ) ? $mapto[ $index ] : '' );
589 ?>
590 <select name="mapto[<?php echo $index; ?>]">
591 <?php $this->get_dropdown_option_html( $default, $current_mapto, $value ); ?>
592
593 <optgroup label="<?php _e( 'Donations', 'give' ); ?>">
594 <?php
595 $this->get_dropdown_option_html( give_import_donations_options(), $current_mapto, $value );
596 ?>
597 </optgroup>
598
599 <optgroup label="<?php _e( 'Donors', 'give' ); ?>">
600 <?php
601 $this->get_dropdown_option_html( give_import_donor_options(), $current_mapto, $value );
602 ?>
603 </optgroup>
604
605 <optgroup label="<?php _e( 'Forms', 'give' ); ?>">
606 <?php
607 $this->get_dropdown_option_html( give_import_donation_form_options(), $current_mapto, $value );
608 ?>
609 </optgroup>
610
611 <?php
612 /**
613 * Fire the action
614 * You can use this filter to add new options.
615 *
616 * @since 1.8.15
617 */
618 do_action( 'give_import_dropdown_option', $index, $value, $mapto, $current_mapto );
619 ?>
620 </select>
621 <?php
622 }
623
624 /**
625 * Print the option html for select in importer
626 *
627 * @since 1.8.15
628 * @access public
629 *
630 * @param array $options
631 * @param string $current_mapto
632 * @param bool $value
633 *
634 * @return void
635 */
636 public function get_dropdown_option_html( $options, $current_mapto, $value = false ) {
637
638 foreach ( $options as $option => $option_value ) {
639 $ignore = array();
640 if ( isset( $option_value['ignore'] ) && is_array( $option_value['ignore'] ) ) {
641 $ignore = $option_value['ignore'];
642 unset( $option_value['ignore'] );
643 }
644
645 $option_value_texts = (array) $option_value;
646 $option_text = $option_value_texts[0];
647
648 $checked = ( ( $current_mapto === $option ) ? 'selected' : false );
649 if ( empty( $checked ) && ! in_array( $value, $ignore ) ) {
650 foreach ( $option_value_texts as $option_value_text ) {
651 $checked = $this->selected( $option_value_text, $value );
652 if ( $checked ) {
653 break;
654 }
655 }
656 }
657
658 echo sprintf(
659 '<option value="%1$s" %2$s >%3$s</option>',
660 $option,
661 $checked,
662 $option_text
663 );
664 }
665 }
666
667 /**
668 * Get column count of csv file.
669 *
670 * @since 1.8.14
671 *
672 * @param $file_id
673 *
674 * @return bool|int
675 */
676 public function get_csv_total( $file_id ) {
677 $total = false;
678 if ( $file_id ) {
679 $file_dir = get_attached_file( $file_id );
680 if ( $file_dir ) {
681 $total = $this->get_csv_data_from_file_dir( $file_dir );
682 }
683 }
684
685 return $total;
686 }
687
688 /**
689 * Get data from File
690 *
691 * @since 2.1
692 *
693 * @param $file_dir
694 *
695 * @return bool|int
696 */
697 public function get_csv_data_from_file_dir( $file_dir ) {
698 $total = false;
699 if ( $file_dir ) {
700 $file = new SplFileObject( $file_dir, 'r' );
701 $file->seek( PHP_INT_MAX );
702 $total = $file->key() + 1;
703 }
704
705 return $total;
706 }
707
708 /**
709 * Get the CSV fields title from the CSV.
710 *
711 * @since 1.8.14
712 *
713 * @param (int) $file_id
714 * @param int $index
715 * @param string $delimiter
716 *
717 * @return array|bool $raw_data title of the CSV file fields
718 */
719 public function get_importer( $file_id, $index = 0, $delimiter = 'csv' ) {
720 /**
721 * Filter to modify delimiter of Import.
722 *
723 * @since 1.8.14
724 *
725 * Return string $delimiter.
726 */
727 $delimiter = (string) apply_filters( 'give_import_delimiter_set', $delimiter );
728
729 $raw_data = false;
730 $file_dir = get_attached_file( $file_id );
731 if ( $file_dir ) {
732 if ( false !== ( $handle = fopen( $file_dir, 'r' ) ) ) {
733 $raw_data = fgetcsv( $handle, $index, $delimiter );
734 // Remove BOM signature from the first item.
735 if ( isset( $raw_data[0] ) ) {
736 $raw_data[0] = $this->remove_utf8_bom( $raw_data[0] );
737 }
738 }
739 }
740
741 return $raw_data;
742 }
743
744 /**
745 * Remove UTF-8 BOM signature.
746 *
747 * @since 1.8.14
748 *
749 * @param string $string String to handle.
750 *
751 * @return string
752 */
753 public function remove_utf8_bom( $string ) {
754 if ( 'efbbbf' === substr( bin2hex( $string ), 0, 6 ) ) {
755 $string = substr( $string, 3 );
756 }
757
758 return $string;
759 }
760
761 /**
762 * Is used to show the process when user upload the donor form.
763 *
764 * @since 1.8.14
765 */
766 public function render_progress() {
767 $step = $this->get_step();
768 ?>
769 <ol class="give-progress-steps">
770 <li class="<?php echo( 1 === $step ? 'active' : '' ); ?>">
771 <?php _e( 'Upload CSV file', 'give' ); ?>
772 </li>
773 <li class="<?php echo( 2 === $step ? 'active' : '' ); ?>">
774 <?php _e( 'Column mapping', 'give' ); ?>
775 </li>
776 <li class="<?php echo( 3 === $step ? 'active' : '' ); ?>">
777 <?php _e( 'Import', 'give' ); ?>
778 </li>
779 <li class="<?php echo( 4 === $step ? 'active' : '' ); ?>">
780 <?php _e( 'Done!', 'give' ); ?>
781 </li>
782 </ol>
783 <?php
784 }
785
786 /**
787 * Will return the import step.
788 *
789 * @since 1.8.14
790 *
791 * @return int $step on which step doest the import is on.
792 */
793 public function get_step() {
794 $step = (int) ( isset( $_REQUEST['step'] ) ? give_clean( $_REQUEST['step'] ) : 0 );
795 $on_step = 1;
796
797 if ( empty( $step ) || 1 === $step ) {
798 $on_step = 1;
799 } elseif ( $this->check_for_dropdown_or_import() ) {
800 $on_step = 3;
801 } elseif ( 2 === $step ) {
802 $on_step = 2;
803 } elseif ( 4 === $step ) {
804 $on_step = 4;
805 }
806
807 return $on_step;
808 }
809
810 /**
811 * Render donations import page
812 *
813 * @since 1.8.14
814 */
815 public function render_page() {
816 include_once GIVE_PLUGIN_DIR . 'includes/admin/tools/views/html-admin-page-import-donations.php';
817 }
818
819 /**
820 * Print Dry Run HTML on donation import page
821 *
822 * @since 2.1
823 */
824 public function give_import_donation_submit_button_render_media_csv() {
825 $dry_run = isset( $_POST['dry_run'] ) ? absint( $_POST['dry_run'] ) : 1;
826 ?>
827 <div>
828 <label for="dry_run">
829 <input type="hidden" name="dry_run" value="0"/>
830 <input type="checkbox" name="dry_run" id="dry_run" class="dry_run"
831 value="1" <?php checked( 1, $dry_run ); ?> >
832 <strong><?php _e( 'Dry Run', 'give' ); ?></strong>
833 </label>
834 <p class="give-field-description">
835 <?php
836 _e( 'Preview what the import would look like without making any default changes to your site or your database.', 'give' );
837 ?>
838 </p>
839 </div>
840 <?php
841 }
842
843 /**
844 * Change submit button text on first step of importing donation.
845 *
846 * @since 2.1
847 *
848 * @param $text
849 *
850 * @return string
851 */
852 function give_import_donation_submit_text_render_media_csv( $text ) {
853 return __( 'Begin Import', 'give' );
854 }
855
856 /**
857 * Add CSV upload HTMl
858 *
859 * Print the html of the file upload from which CSV will be uploaded.
860 *
861 * @since 1.8.14
862 * @return void
863 */
864 public function render_media_csv() {
865 add_filter( 'give_import_donation_submit_button_text', array(
866 $this,
867 'give_import_donation_submit_text_render_media_csv'
868 ) );
869 add_action( 'give_import_donation_submit_button', array(
870 $this,
871 'give_import_donation_submit_button_render_media_csv'
872 ) );
873 ?>
874 <tr valign="top">
875 <th colspan="2">
876 <h2 id="give-import-title"><?php _e( 'Import donations from a CSV file', 'give' ) ?></h2>
877 <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>
878 </th>
879 </tr>
880 <?php
881 $csv = ( isset( $_POST['csv'] ) ? give_clean( $_POST['csv'] ) : '' );
882 $csv_id = ( isset( $_POST['csv_id'] ) ? give_clean( $_POST['csv_id'] ) : '' );
883 $delimiter = ( isset( $_POST['delimiter'] ) ? give_clean( $_POST['delimiter'] ) : 'csv' );
884 $mode = empty( $_POST['mode'] ) ?
885 'disabled' :
886 ( give_is_setting_enabled( give_clean( $_POST['mode'] ) ) ? 'enabled' : 'disabled' );
887 $create_user = empty( $_POST['create_user'] ) ?
888 'disabled' :
889 ( give_is_setting_enabled( give_clean( $_POST['create_user'] ) ) ? 'enabled' : 'disabled' );
890 $delete_csv = empty( $_POST['delete_csv'] ) ?
891 'enabled' :
892 ( give_is_setting_enabled( give_clean( $_POST['delete_csv'] ) ) ? 'enabled' : 'disabled' );
893
894 // Reset csv and csv_id if csv
895 if ( empty( $csv_id ) || ! $this->is_valid_csv( $csv_id, $csv ) ) {
896 $csv_id = $csv = '';
897 }
898 $per_page = isset( $_POST['per_page'] ) ? absint( $_POST['per_page'] ) : self::$per_page;
899
900 $sample_file_text = sprintf(
901 '%s <a href="%s">%s</a>.',
902 __( 'Download the sample file', 'give' ),
903 esc_url( GIVE_PLUGIN_URL . 'sample-data/sample-data.csv' ),
904 __( 'here', 'give' )
905 );
906
907 $csv_description = sprintf(
908 '%1$s %2$s',
909 __( 'The file must be a Comma Seperated Version (CSV) file type only.', 'give' ),
910 $sample_file_text
911 );
912
913 $settings = array(
914 array(
915 'id' => 'csv',
916 'name' => __( 'Choose a CSV file:', 'give' ),
917 'type' => 'file',
918 'attributes' => array( 'editing' => 'false', 'library' => 'text' ),
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( (array) apply_filters( 'give_import_step_two_url', array(
1010 'step' => '2',
1011 'importer-type' => $this->importer_type,
1012 'csv' => $csv_id,
1013 'delimiter' => isset( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : 'csv',
1014 'mode' => empty( $_POST['mode'] ) ?
1015 '0' :
1016 ( give_is_setting_enabled( give_clean( $_POST['mode'] ) ) ? '1' : '0' ),
1017 'create_user' => empty( $_POST['create_user'] ) ?
1018 '0' :
1019 ( give_is_setting_enabled( give_clean( $_POST['create_user'] ) ) ? '1' : '0' ),
1020 'delete_csv' => empty( $_POST['delete_csv'] ) ?
1021 '1' :
1022 ( give_is_setting_enabled( give_clean( $_POST['delete_csv'] ) ) ? '1' : '0' ),
1023 'per_page' => isset( $_POST['per_page'] ) ? absint( $_POST['per_page'] ) : self::$per_page,
1024 'dry_run' => isset( $_POST['dry_run'] ) ? absint( $_POST['dry_run'] ) : 0,
1025 ) ) );
1026
1027 $this->is_csv_valid = $url;
1028 }
1029 }
1030 }
1031
1032 /**
1033 * Check if user uploaded csv is valid or not.
1034 *
1035 * @since 1.8.14
1036 * @access public
1037 *
1038 * @param mixed $csv ID of the CSV files.
1039 * @param string $match_url ID of the CSV files.
1040 *
1041 * @return bool $has_error CSV is valid or not.
1042 */
1043 private function is_valid_csv( $csv = false, $match_url = '' ) {
1044 $is_valid_csv = true;
1045
1046 if ( $csv ) {
1047 $csv_url = wp_get_attachment_url( $csv );
1048
1049 $delimiter = ( ! empty( $_REQUEST['delimiter'] ) ? give_clean( $_REQUEST['delimiter'] ) : 'csv' );
1050
1051 if (
1052 ! $csv_url ||
1053 ( ! empty( $match_url ) && ( $csv_url !== $match_url ) ) ||
1054 ( ( $mime_type = get_post_mime_type( $csv ) ) && ! strpos( $mime_type, $delimiter ) )
1055 ) {
1056 $is_valid_csv = false;
1057 Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid CSV file.', 'give' ) );
1058 }
1059 } else {
1060 $is_valid_csv = false;
1061 Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid CSV file.', 'give' ) );
1062 }
1063
1064 return $is_valid_csv;
1065 }
1066
1067
1068 /**
1069 * Render report import field
1070 *
1071 * @since 1.8.14
1072 * @access public
1073 *
1074 * @param $field
1075 * @param $option_value
1076 */
1077 public function render_import_field( $field, $option_value ) {
1078 include_once GIVE_PLUGIN_DIR . 'includes/admin/tools/views/html-admin-page-imports.php';
1079 }
1080
1081 /**
1082 * Get if current page import donations page or not
1083 *
1084 * @since 1.8.14
1085 * @return bool
1086 */
1087 private function is_donations_import_page() {
1088 return 'import' === give_get_current_setting_tab() &&
1089 isset( $_GET['importer-type'] ) &&
1090 $this->importer_type === give_clean( $_GET['importer-type'] );
1091 }
1092 }
1093
1094 Give_Import_Donations::get_instance()->setup();
1095 }
1096