PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.17.0
GiveWP – Donation Plugin and Fundraising Platform v4.17.0
4.17.0 4.16.9 4.16.8.1 4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 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 All 256 releases
← All changes | includes/admin/tools/export/give-export-donations-exporter.php +116 -11 2.3.0 → 4.17.0 View file →
@@ -5,9 +5,9 @@
5 5 * This class handles payment export in batches.
6 6 *
7 7 * @package Give
8 8 * @subpackage Admin/Reports
9 - * @copyright Copyright (c) 2016, WordImpress
9 + * @copyright Copyright (c) 2016, GiveWP
10 10 * @license https://opensource.org/licenses/gpl-license GNU Public License
11 11 * @since 2.1
12 12 */
13 13
@@ -95,11 +95,11 @@
95 95 $this->form = $this->data['forms'];
96 96 $this->categories = ! empty( $request['give_forms_categories'] ) ? (array) $request['give_forms_categories'] : array();
97 97 $this->tags = ! empty( $request['give_forms_tags'] ) ? (array) $request['give_forms_tags'] : array();
98 98 $this->form_id = $this->get_form_ids( $request );
99 - $this->price_id = isset( $request['give_price_option'] ) && ( 'all' !== $request['give_price_option'] && '' !== $request['give_price_option'] ) ? absint( $request['give_price_option'] ) : null;
100 - $this->start = isset( $request['start'] ) ? sanitize_text_field( $request['start'] ) : '';
101 - $this->end = isset( $request['end'] ) ? sanitize_text_field( $request['end'] ) : '';
99 + $this->price_id = isset( $request['give_price_option'] ) && ! in_array( $this->price_id, array( 'all', '' ) ) ? absint( $request['give_price_option'] ) : null;
100 + $this->start = ! empty( $request['start'] ) ? date( 'Y-m-d', strtotime( $request['start'] ) ) : '';
101 + $this->end = ! empty( $request['end'] ) ? date( 'Y-m-d', strtotime( $request['end'] ) ) : '';
102 102 $this->status = isset( $request['status'] ) ? sanitize_text_field( $request['status'] ) : 'complete';
103 103
104 104 /**
105 105 * Hook to use after setting properties.
@@ -156,8 +156,9 @@
156 156
157 157 /**
158 158 * CSV file columns.
159 159 *
160 + * @since 3.12.1 add phone column.
160 161 * @since 2.1
161 162 *
162 163 * @param array $columns
163 164 *
@@ -198,8 +199,11 @@
198 199 $cols['address_state'] = __( 'State', 'give' );
199 200 $cols['address_zip'] = __( 'Zip', 'give' );
200 201 $cols['address_country'] = __( 'Country', 'give' );
201 202 break;
203 + case 'phone':
204 + $cols['phone'] = __( 'Donor Phone Number', 'give' );
205 + break;
202 206 case 'comment':
203 207 $cols['comment'] = __( 'Donor Comment', 'give' );
204 208 break;
205 209 case 'donation_total':
@@ -215,8 +219,9 @@
215 219 $cols['donation_status'] = __( 'Donation Status', 'give' );
216 220 break;
217 221 case 'payment_gateway':
218 222 $cols['payment_gateway'] = __( 'Payment Gateway', 'give' );
223 + break;
219 224 case 'payment_mode':
220 225 $cols['payment_mode'] = __( 'Payment Mode', 'give' );
221 226 break;
222 227 case 'form_id':
@@ -245,8 +250,14 @@
245 250 break;
246 251 case 'donor_ip':
247 252 $cols['donor_ip'] = __( 'Donor IP Address', 'give' );
248 253 break;
254 + case 'donation_note_private':
255 + $cols['donation_note_private'] = __( 'Donation Note (private)', 'give' );
256 + break;
257 + case 'donation_note_to_donor':
258 + $cols['donation_note_to_donor'] = __( 'Donation Note (to donor)', 'give' );
259 + break;
249 260 default:
250 261 $cols[ $key ] = $key;
251 262
252 263 }
@@ -276,18 +287,17 @@
276 287 $defaults = array(
277 288 'number' => 30,
278 289 'page' => $this->step,
279 290 'status' => $this->status,
291 + 'order' => 'ASC',
280 292 );
281 293 // Date query.
282 294 if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
283 295 if ( ! empty( $this->start ) ) {
284 - $start_date = give_get_formatted_date( $this->start );
285 - $defaults['date_query'][0]['after'] = "{$start_date} 00:00:00";
296 + $defaults['date_query'][0]['after'] = "{$this->start} 00:00:00";
286 297 }
287 298 if ( ! empty( $this->end ) ) {
288 - $end_date = give_get_formatted_date( $this->end );
289 - $defaults['date_query'][0]['before'] = "{$end_date} 23:59:59";
299 + $defaults['date_query'][0]['before'] = "{$this->end} 23:59:59";
290 300 }
291 301 }
292 302
293 303 if ( ! empty( $this->form_id ) ) {
@@ -307,8 +317,9 @@
307 317 * Get the Export Data.
308 318 *
309 319 * @access public
310 320 *
321 + * @since 3.12.1 add donor phone.
311 322 * @since 2.1
312 323 *
313 324 * @global object $wpdb Used to query the database using the WordPress database API.
314 325 *
@@ -367,8 +378,12 @@
367 378 $data[ $i ]['address_zip'] = isset( $address['zip'] ) ? $address['zip'] : '';
368 379 $data[ $i ]['address_country'] = isset( $address['country'] ) ? $address['country'] : '';
369 380 }
370 381
382 + if ( ! empty( $columns['phone'] ) ) {
383 + $data[ $i ]['phone'] = $payment_meta['_give_payment_donor_phone'];
384 + }
385 +
371 386 if ( ! empty( $columns['comment'] ) ) {
372 387 $comment = give_get_donor_donation_comment( $payment->ID, $payment->donor_id );
373 388 $data[ $i ]['comment'] = ! empty( $comment ) ? $comment->comment_content : '';
374 389 }
@@ -418,9 +433,9 @@
418 433 if ( 'custom' === $payment->price_id ) {
419 434 $custom_amount_text = give_get_meta( $payment->form_id, '_give_custom_amount_text', true );
420 435
421 436 if ( empty( $custom_amount_text ) ) {
422 - $custom_amount_text = esc_html__( 'Custom', 'give' );
437 + $custom_amount_text = esc_html__( 'Custom Amount', 'give' );
423 438 }
424 439 $data[ $i ]['form_level_title'] = $custom_amount_text;
425 440 } else {
426 441 $data[ $i ]['form_level_title'] = give_get_price_option_name( $payment->form_id, $payment->price_id );
@@ -449,8 +464,71 @@
449 464 if ( ! empty( $columns['donor_ip'] ) ) {
450 465 $data[ $i ]['donor_ip'] = give_get_payment_user_ip( $payment->ID );
451 466 }
452 467
468 + if ( ! empty( $columns['donation_note_private'] ) ) {
469 + $comments = Give()->comment->db->get_comments(
470 + array(
471 + 'comment_parent' => $payment->ID,
472 + 'comment_type' => 'donation',
473 + 'meta_query' => array(
474 + 'relation' => 'OR',
475 + array(
476 + 'key' => 'note_type',
477 + 'compare' => 'NOT EXISTS',
478 + ),
479 + array(
480 + 'key' => 'note_type',
481 + 'value' => 'donor',
482 + 'compare' => '!=',
483 + ),
484 + ),
485 + )
486 + );
487 +
488 + $comment_html = array();
489 +
490 + if ( ! empty( $comments ) ) {
491 + foreach ( $comments as $comment ) {
492 + $comment_html[] = sprintf(
493 + '%s - %s',
494 + date( 'Y-m-d', strtotime( $comment->comment_date ) ),
495 + $comment->comment_content
496 + );
497 + }
498 + }
499 +
500 + $data[ $i ]['donation_note_private'] = implode( "\n", $comment_html );
501 + }
502 +
503 + if ( ! empty( $columns['donation_note_to_donor'] ) ) {
504 + $comments = Give()->comment->db->get_comments(
505 + array(
506 + 'comment_parent' => $payment->ID,
507 + 'comment_type' => 'donation',
508 + 'meta_query' => array(
509 + array(
510 + 'key' => 'note_type',
511 + 'value' => 'donor',
512 + ),
513 + ),
514 + )
515 + );
516 +
517 + $comment_html = array();
518 +
519 + if ( ! empty( $comments ) ) {
520 + foreach ( $comments as $comment ) {
521 + $comment_html[] = sprintf(
522 + '%s - %s',
523 + date( 'Y-m-d', strtotime( $comment->comment_date ) ),
524 + $comment->comment_content
525 + );
526 + }
527 + }
528 + $data[ $i ]['donation_note_to_donor'] = implode( "\n", $comment_html );
529 + }
530 +
453 531 // Add custom field data.
454 532 // First we remove the standard included keys from above.
455 533 $remove_keys = array(
456 534 'donation_id',
@@ -539,9 +617,14 @@
539 617 *
540 618 * @return int
541 619 */
542 620 public function get_percentage_complete() {
543 - $args = $this->get_donation_argument( array( 'number' => - 1 ) );
621 + $args = $this->get_donation_argument(
622 + array(
623 + 'number' => - 1,
624 + 'output' => '',
625 + )
626 + );
544 627 if ( isset( $args['page'] ) ) {
545 628 unset( $args['page'] );
546 629 }
547 630 $query = give_get_payments( $args );
@@ -562,8 +645,9 @@
562 645 *
563 646 * @access public
564 647 *
565 648 * @since 2.1
649 + * @since 3.14.0 Use maybe_serialize() for column data (some data are arrays)
566 650 *
567 651 * @return string|false
568 652 */
569 653 public function print_csv_rows() {
@@ -579,9 +663,10 @@
579 663 $i = 1;
580 664 foreach ( $row as $col_id => $column ) {
581 665 // Make sure the column is valid
582 666 if ( array_key_exists( $col_id, $cols ) ) {
583 - $row_data .= '"' . preg_replace( '/"/', "'", $column ) . '"';
667 + $column = maybe_serialize( $column );
668 + $row_data .= '"' . $this->escape_csv_cell_data(preg_replace( '/"/', "'", $column )) . '"';
584 669 $row_data .= $i == count( $cols ) ? '' : ',';
585 670 $i ++;
586 671 }
587 672 }
@@ -594,5 +679,25 @@
594 679 }
595 680
596 681 return false;
597 682 }
683 +
684 + /**
685 + * Escapes CSV cell data to protect against CSV injection.
686 + * @link https://owasp.org/www-community/attacks/CSV_Injection
687 + *
688 + * @since 3.12.1 sanitize + prefix
689 + * @since 2.25.2
690 + *
691 + * @param mixed|string $cellData
692 + *
693 + * @return mixed|string
694 + */
695 + protected function escape_csv_cell_data($cellData) {
696 + $cellData = str_replace('+', '', $cellData);
697 + $firstCharacter = substr($cellData, 0, 1);
698 + if( in_array($firstCharacter, array('=', '+', '-', '@')) ) {
699 + $cellData = "'" . $cellData;
700 + }
701 + return $cellData;
702 + }
598 703 }