PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.7.0.12
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.7.0.12
1.8.13.1 1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 All 212 releases
charitable / includes / admin / import-items / class-charitable-import-items.php

class-charitable-import-items.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.7.0.12, at includes/admin/import-items/class-charitable-import-items.php

564 lines 23.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * This class is responsible for adding the Charitable admin pages.
4 *
5 * @package Charitable/Classes/Charitable_Import_Items
6 * @author David Bisset
7 * @copyright Copyright (c) 2022, WP Charitable LLC
8 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 * @since 1.7.0.7
10 */
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 if ( ! class_exists( 'Charitable_Import_Items' ) ) :
18
19 /**
20 * Charitable_Import_Items
21 *
22 * @since 1.7.0.7
23 */
24 final class Charitable_Import_Items {
25
26 /**
27 * The single instance of this class.
28 *
29 * @var Charitable_Import_Items|null
30 */
31 private static $instance = null;
32
33 /**
34 * Holds any plugin error messages.
35 *
36 * @since 1.0.0
37 *
38 * @var array
39 */
40 public $errors = array();
41
42 /**
43 * Create class object.
44 *
45 * @since 1.7.0.7
46 */
47 private function __construct() {
48 }
49
50 /**
51 * Returns and/or create the single instance of this class.
52 *
53 * @since 1.7.0.7
54 *
55 * @return Charitable_Import_Items
56 */
57 public static function get_instance() {
58 if ( is_null( self::$instance ) ) {
59 self::$instance = new self();
60 }
61
62 return self::$instance;
63 }
64
65 /**
66 * This forces the charitable menu to be open for category and tag pages.
67 *
68 * @since 1.7.0.7
69 *
70 * @return string
71 */
72 public function admin_accept_import_campaign_request() {
73
74 global $wpdb;
75
76 if ( ! is_admin() || empty( $_POST ) ) {
77 return;
78 }
79
80 if (! isset( $_POST['charitable_nonce'] ) || ! wp_verify_nonce( $_POST['charitable_nonce'], 'import_campaign' ) ) {
81 return;
82 }
83
84 if ( ! $this->has_json_extension() ) {
85 $this->errors[] = __( 'Sorry, but Envira Gallery import files must be in <code>.json</code> format.', 'envira-gallery' );
86 $redirect_link = admin_url( 'admin.php?page=charitable-settings&tab=tools' );
87 wp_safe_redirect( $redirect_link );
88 exit;
89 }
90
91 // Retrieve the JSON contents of the file. If that fails, return an error.
92 $contents = $this->get_file_contents();
93 if ( ! $contents ) {
94 $this->errors[] = __( 'Sorry, but there was an error retrieving the contents of the campaign export file. Please try again.', 'envira-gallery' );
95 $redirect_link = admin_url( 'admin.php?page=charitable-settings&tab=tools' );
96 wp_safe_redirect( $redirect_link );
97 exit;
98 }
99
100 // Decode the settings and start processing.
101 $data = json_decode( $contents, true );
102
103 // get the old post ID as we assign the new one, as we will want to document this as metadata.
104 $old_post_id = $data['post']['ID'];
105
106 // since we don't import authors/campaign creators, determine if the email address of the campaign creater exists in this site.
107 $old_post_author_email = $data['campaign_creator']['user_email'];
108 $campaign_creator = get_user_by('email', $old_post_author_email );
109 if ( $campaign_creator ) {
110 $campaign_creator_id = $campaign_creator->ID;
111 } else {
112 // assign it to the user who is logged in?
113 $campaign_creator_id = get_current_user_id();
114 }
115
116 $campaign_data = array(
117 'post_title' => $data['post']['post_title'],
118 'post_content' => $data['post']['post_content'],
119 'post_excerpt' => $data['post']['post_excerpt'],
120 'post_date' => $data['post']['post_date'],
121 'post_date_gmt' => $data['post']['post_date_gmt'],
122 'comment_status' => $data['post']['comment_status'],
123 'ping_status' => $data['post']['ping_status'],
124 'post_name' => $data['post']['post_name'],
125 'post_modified' => $data['post']['post_modified'],
126 'post_modified_gmt' => $data['post']['post_modified_gmt'],
127 'post_content_filtered' => $data['post']['post_content_filtered'],
128 'guid' => $data['post']['guid'],
129 'post_mime_type' => $data['post']['post_mime_type'],
130 'comment_count' => $data['post']['comment_count'],
131 'post_status' => 'draft',
132 'post_type' => 'campaign',
133 'post_author' => $campaign_creator_id,
134 );
135 $campaign_id = wp_insert_post( $campaign_data );
136
137 foreach ( $data['meta'] as $meta_import_id => $meta_to_import ) {
138 if ( is_serialized( $meta_to_import['meta_value'] ) ) {
139 $data_to_import = unserialize( $meta_to_import['meta_value'] );
140 } else {
141 $data_to_import = $meta_to_import['meta_value'];
142 }
143 add_post_meta( $campaign_id, $meta_to_import['meta_key'], $data_to_import );
144 }
145
146 add_post_meta( $campaign_id,'_campaign_imported_campaign_key', intval( $old_post_id ) );
147
148 // categories and tags
149 if ( isset( $data['campaign_category'] ) && ! empty( $data['campaign_category'] ) ) {
150 foreach ( $data['campaign_category'] as $term_to_import ) {
151 $term = term_exists( $term_to_import['slug'], 'campaign_category' );
152 if ( ! $term ) { // create category }
153 $term_id = wp_insert_term(
154 $term_to_import['name'], // the term
155 'campaign_category', // the taxonomy
156 array(
157 'description' => $term_to_import['description'],
158 'slug' => $term_to_import['slug'],
159 )
160 );
161 } else {
162 $term_id = intval( $term['term_id'] );
163 }
164 wp_set_post_terms( $campaign_id, array( $term_id ), 'campaign_category', true );
165
166 }
167 }
168 if ( isset( $data['campaign_tag'] ) && ! empty( $data['campaign_tag'] ) ) {
169 foreach ( $data['campaign_tag'] as $term_to_import ) {
170 $term = term_exists( $term_to_import['slug'], 'campaign_tag' );
171 if ( ! $term ) { // create category }
172 $term_id = wp_insert_term(
173 $term_to_import['name'], // the term
174 'campaign_tag', // the taxonomy
175 array(
176 'description' => $term_to_import['description'],
177 'slug' => $term_to_import['slug'],
178 )
179 );
180 } else {
181 $term_id = intval( $term['term_id'] );
182 }
183 wp_set_post_terms( $campaign_id, array( $term_id ), 'campaign_tag', true );
184
185 }
186 }
187
188 // get featured image
189 if ( isset( $data['thumbnail'] ) && ! empty( $data['thumbnail'] ) ) {
190
191 // Add Featured Image to Post
192 // $image_url = esc_url( $data['thumbnail'] ); // Define the image URL here
193 // $image_name = basename( $data['thumbnail'] );
194 // $upload_dir = wp_upload_dir(); // Set upload folder
195 // $image_data = file_get_contents( $image_url ); // Get image data
196 // $unique_file_name = wp_unique_filename( $upload_dir['path'], $image_name ); // Generate unique name
197 // $filename = basename( $unique_file_name ); // Create image file name
198
199 // Prepare variables.
200 $src = esc_url( $data['thumbnail'] );
201 $stream = wp_remote_get( $src, array( 'timeout' => 60 ) );
202 $type = wp_remote_retrieve_header( $stream, 'content-type' );
203 $filename = basename( $src );
204 $fileinfo = pathinfo( $filename );
205
206 // If the filename doesn't have an extension on it, determine the filename to use to save this image to the Media Library
207 // This fixes importing URLs with no file extension e.g. http://placehold.it/300x300 (which is a PNG).
208 if ( ! isset( $fileinfo['extension'] ) || empty( $fileinfo['extension'] ) ) {
209 switch ( $type ) {
210 case 'image/jpeg':
211 $filename = $filename . '.jpeg';
212 break;
213 case 'image/jpg':
214 $filename = $filename . '.jpg';
215 break;
216 case 'image/gif':
217 $filename = $filename . '.gif';
218 break;
219 case 'image/png':
220 $filename = $filename . '.png';
221 break;
222 case 'image/webp':
223 $filename = $filename . '.webp';
224 break;
225 }
226 }
227
228 // If we cannot get the image or determine the type, bail.
229 if ( is_wp_error( $stream ) ) {
230
231 if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
232 error_log ('admin_accept_import_campaign_request:: ');
233 error_log ( print_r( $stream, true ) );
234 }
235
236 } elseif ( ! $type || strpos( $type, 'text/html' ) !== false ) {
237
238 if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
239 error_log ('admin_accept_import_campaign_request type: ');
240 error_log ( print_r( $type, true ) );
241 }
242
243 } else {
244 // It is an image. Stream the image.
245 $mirror = wp_upload_bits( $filename, null, wp_remote_retrieve_body( $stream ) );
246
247 // If there is an error, bail.
248 if ( ! empty( $mirror['error'] ) ) {
249
250 if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
251 error_log ('admin_accept_import_campaign_request:: ');
252 error_log ( print_r( $stream, true ) );
253 }
254
255 } else {
256 // Check if the $item has title, caption, alt specified
257 // If so, store those values against the attachment so they're included in the Gallery
258 // If not, fallback to the defaults.
259 $attachment = array(
260 'post_title' => ( ( isset( $data['post']['post_title'] ) && ! empty($data['post']['post_title'] ) ) ? $data['post']['post_title'] : urldecode( $filename ) ), // Title.
261 'post_mime_type' => $type,
262 'post_excerpt' => ( ( isset( $data['post']['post_excerpt'] ) && ! empty( $data['post']['post_excerpt'] ) ) ? $data['post']['post_excerpt'] : '' ), // Caption.
263 );
264 $attach_id = wp_insert_attachment( $attachment, $mirror['file'], $campaign_id );
265 if ( ( isset( $item['alt'] ) && ! empty( $item['alt'] ) ) ) {
266 update_post_meta( $attach_id, '_wp_attachment_image_alt', $item['alt'] );
267 }
268
269 // Generate and update attachment metadata.
270 if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
271 require ABSPATH . 'wp-admin/includes/image.php';
272 }
273
274 // Generate and update attachment metadata.
275 $attach_data = wp_generate_attachment_metadata( $attach_id, $mirror['file'] );
276 wp_update_attachment_metadata( $attach_id, $attach_data );
277
278 // And finally assign featured image to post
279 set_post_thumbnail( $campaign_id, $attach_id );
280
281 }
282 }
283
284 }
285
286 $this->add_update_message( __( 'Campaign imported.', 'charitable' ) . ' <a href="' . admin_url( 'post.php?post=' . $campaign_id . '&action=edit' ) . '">View campaign</a>.', 'success' );
287
288 $redirect_link = admin_url( 'admin.php?page=charitable-settings&tab=tools' );
289 wp_safe_redirect( $redirect_link );
290 exit;
291
292 }
293
294 /**
295 * This forces the charitable menu to be open for category and tag pages.
296 *
297 * @since 1.7.0.7
298 *
299 * @return string
300 */
301 public function admin_accept_import_donations_request() {
302
303 global $wpdb;
304
305 if ( ! is_admin() || empty( $_POST ) ) {
306 return;
307 }
308
309 if ( ! isset( $_POST['charitable_nonce'] ) || ! wp_verify_nonce( $_POST['charitable_nonce'], 'import_donations' ) ) {
310 return;
311 }
312
313 if ( ! $this->has_json_extension('import_donations' ) ) {
314 $this->add_update_message( __( 'Sorry, but Envira Gallery import files must be in <code>.json</code> format.', 'charitable' ), 'error' );
315 $redirect_link = admin_url( 'admin.php?page=charitable-settings&tab=tools' );
316 wp_safe_redirect( $redirect_link );
317 exit;
318 }
319
320 // Retrieve the JSON contents of the file. If that fails, return an error.
321 $contents = $this->get_file_contents( 'import_donations' );
322 if ( ! $contents ) {
323 $this->add_update_message( __( 'Sorry, but there was an error retrieving the contents of the donation export file. Please try again.', 'charitable' ), 'error' );
324 $redirect_link = admin_url( 'admin.php?page=charitable-settings&tab=tools' );
325 wp_safe_redirect( $redirect_link );
326 exit;
327 }
328
329 // Decode the settings and start processing.
330 $data = json_decode( $contents, true );
331
332 // Get the campaign we are importing these donations into, otherwise bail.
333 $campaign_id = isset( $_POST['charitable_settings']['tools_campaign'] ) ? intval( $_POST['charitable_settings']['tools_campaign'] ) : false;
334
335 if ( false === $campaign_id || ! isset( $data['campaigns'] ) || count( $data['campaigns'] ) === 0 ) {
336 $this->add_update_message( __( 'Sorry, but there was an error attempting to determine the campaign ID for this import. Please try again.', 'charitable' ), 'error' );
337 $redirect_link = admin_url( 'admin.php?page=charitable-settings&tab=tools' );
338 wp_safe_redirect( $redirect_link );
339 exit;
340 }
341
342 $campaign_name = get_the_title( $campaign_id ) ? get_the_title( $campaign_id ) : 'Unknown Campaign';
343 $donations_added = 0;
344
345 foreach ( $data['campaigns'] as $old_campaign_id => $campaign_donations_info ) {
346 foreach ( $campaign_donations_info['donation_posts'] as $old_donation_id => $donation_data ) {
347
348 $donor_data = false;
349 $found_key = false;
350 $donation_log = array();
351
352 if ( ! isset( $data['campaigns'][ $old_campaign_id ]['charitable_campaign_donations'] ) ) {
353 continue;
354 }
355
356 // confirm the existance of the extra table data, otherwise adding this donation is meaningless.
357 foreach ( $campaign_donations_info['charitable_campaign_donations'] as $key => $charitable_campaign_donation ) {
358 if ( intval( $charitable_campaign_donation['donation_id'] ) === $old_donation_id ) {
359 $found_key = $key;
360 }
361 }
362
363 if ( ! $found_key ) {
364 continue;
365 }
366
367 if ( ! isset( $donation_data['post'] ) ) {
368 if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
369 error_log ('import post fail donation data: ');
370 error_log ( print_r( $donation_data, true ) );
371 }
372 return;
373 }
374
375 // create the donation post.
376 $donation_post_args = array(
377 'post_title' => $donation_data['post']['post_title'],
378 'post_content' => $donation_data['post']['post_content'],
379 'post_excerpt' => $donation_data['post']['post_excerpt'],
380 'post_date' => $donation_data['post']['post_date'],
381 'post_date_gmt' => $donation_data['post']['post_date_gmt'],
382 'comment_status' => $donation_data['post']['comment_status'],
383 'ping_status' => $donation_data['post']['ping_status'],
384 'post_name' => $donation_data['post']['post_name'],
385 'post_modified' => $donation_data['post']['post_modified'],
386 'post_modified_gmt' => $donation_data['post']['post_modified_gmt'],
387 'post_content_filtered' => $donation_data['post']['post_content_filtered'],
388 'guid' => $donation_data['post']['guid'],
389 'post_mime_type' => $donation_data['post']['post_mime_type'],
390 'comment_count' => $donation_data['post']['comment_count'],
391 'post_status' => $donation_data['post']['post_status'], // 'charitable-pending',
392 'post_type' => 'donation',
393 'post_author' => $this->get_creator_id( $donation_data['author'] ) // $campaign_creator_id,
394 );
395 $donation_id = wp_insert_post( $donation_post_args );
396
397 // import meta
398 foreach ( $donation_data['meta'] as $meta_import_id => $meta_to_import ) {
399 if ( is_serialized( $meta_to_import['meta_value'] ) ) {
400 $data_to_import = unserialize( $meta_to_import['meta_value'] );
401 } else {
402 $data_to_import = $meta_to_import['meta_value'];
403 }
404 if ( $meta_to_import['meta_key'] === 'donor' ) {
405 $donor_data = unserialize( $meta_to_import['meta_value'] );
406 }
407 if ( $meta_to_import['meta_key'] === '_donation_log' ) {
408 $donation_log = unserialize( $meta_to_import['meta_value'] );
409 }
410
411 add_post_meta( $donation_id, $meta_to_import['meta_key'], $data_to_import );
412 }
413
414 add_post_meta( $donation_id,'_campaign_imported_donation_id', intval( $old_campaign_id ) );
415
416 // determine donor id from the donor data (email is key).
417 $donor_id = $this->get_donor_id( $donor_data ); // $campaign_creator_id,
418
419 // update custom table.
420 $table = $wpdb->prefix . 'charitable_campaign_donations';
421 $args = array(
422 'donation_id' => $donation_id,
423 'donor_id' => $donor_id,
424 'campaign_id' => $campaign_id,
425 'campaign_name' => $campaign_name,
426 'amount' => $campaign_donations_info['charitable_campaign_donations'][ $found_key ]['amount'], // ... and so on
427 );
428
429 $wpdb->insert( $table, $args );
430
431 // update log.
432 $donation_log[] = array ( 'time' => time(), 'message' => 'Donation Imported.' );
433 update_post_meta( $donation_id, '_donation_log', $donation_log );
434
435 $donations_added++;
436
437 }
438 }
439
440 $this->add_update_message( __( $donations_added . ' donations imported.', 'charitable' ), 'success' );
441
442 $redirect_link = admin_url( 'admin.php?page=charitable-settings&tab=tools&status=success+' . $donations_added );
443 wp_safe_redirect( $redirect_link );
444 exit;
445
446 }
447
448 /**
449 * Determines if a gallery import file has a proper file extension.
450 *
451 * @since 1.0.0
452 *
453 * @return bool True if the imported gallery file has a proper file extension, false otherwise.
454 */
455 public function has_json_extension( $import_what = 'import_campaign' ) {
456
457 $file_array = isset( $_FILES['charitable_settings']['name']['tools'][$import_what] ) ? explode( '.', $_FILES['charitable_settings']['name']['tools'][$import_what] ) : null;
458 $extension = end( $file_array );
459 return 'json' === $extension;
460
461 }
462
463 /**
464 * Retrieve the contents of the imported gallery file.
465 *
466 * @since 1.0.0
467 *
468 * @return string|bool JSON contents string if successful, false otherwise.
469 */
470 public function get_file_contents( $import_what = 'import_campaign' ) {
471
472 $file = isset( $_FILES['charitable_settings']['tmp_name']['tools'][$import_what] ) ? wp_unslash( $_FILES['charitable_settings']['tmp_name']['tools'][$import_what] ) : false;
473 return file_get_contents( $file );
474
475 }
476
477 /**
478 * Locate the user id of someone using this email
479 *
480 * @since 1.0.0
481 *
482 * @return string|bool JSON contents string if successful, false otherwise.
483 */
484 public function get_creator_id( $author_data, $zero_allowed = false ) {
485
486 $email = false;
487
488 // try finding a user by email first
489 if ( isset( $author_data['email'] ) ) {
490 $email = $author_data['email'];
491 } else if ( isset( $author_data['user_email'] ) ) {
492 $email = $author_data['user_email'];
493 }
494
495 if ( $email ) {
496 $user = get_user_by( 'email', $email );
497 if ( $user ) {
498 return $user->ID;
499 }
500 }
501
502 return $zero_allowed ? 0 : get_current_user_id();
503
504 }
505
506 /**
507 * Locate the user id of someone using this email
508 *
509 * @since 1.0.0
510 *
511 * @return string|bool JSON contents string if successful, false otherwise.
512 */
513 public function get_donor_id( $donor_data ) {
514
515 global $wpdb;
516
517 $email = esc_html( $donor_data['email'] );
518
519 // update custom table.
520 $table = $wpdb->prefix . 'charitable_donors';
521
522 // try finding if they still exist first.
523 $donor_id = $wpdb->get_var("SELECT donor_id FROM $table WHERE email = '$email'");
524
525 // if not, create it in the table.
526 if ( $donor_id == null) {
527
528 $donor_id = $wpdb->insert( $table, array(
529 'donor_id' => $donor_id,
530 'user_id' => $this->get_creator_id( $donor_data, true ),
531 'email' => $donor_data['email'],
532 'first_name' => $donor_data['first_name'],
533 'last_name' => $donor_data['last_name'],
534 'date_joined' => $donor_data['date_joined'],
535 ));
536
537 }
538
539 return $donor_id;
540 }
541
542 /**
543 * Add an update message.
544 *
545 * @since 1.4.6
546 *
547 * @param string $message The message text.
548 * @param string $type The type of message. Options: 'error', 'success', 'warning', 'info'.
549 * @param boolean $dismissible Whether the message can be dismissed.
550 * @return void
551 */
552 public function add_update_message( $message, $type = 'error', $dismissible = true ) {
553 if ( ! in_array( $type, array( 'error', 'success', 'warning', 'info' ) ) ) {
554 $type = 'error';
555 }
556
557 charitable_get_admin_notices()->add_notice( $message, $type, false, $dismissible );
558 }
559
560
561 }
562
563 endif;
564