PluginProbe
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management / 1.6.1
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management v1.6.1
1.6.1 1.6.0 1.5.1 1.5.0 1.4.0 1.3.0 trunk 0.0.1 1.0.0 1.1.0 1.1.1 1.1.2 1.2.0
← All changes | inc/import-export/import/column-map.php +62 -0 1.4.0 → 1.6.1 View file →
@@ -155,8 +155,13 @@
155 155 'label' => __( 'Donor Comment', 'suredonation' ),
156 156 'aliases' => [ 'donor comment', 'comment', 'donor_comment' ],
157 157 'required' => false,
158 158 ],
159 + 'donor_comment_status' => [
160 + 'label' => __( 'Comment Status', 'suredonation' ),
161 + 'aliases' => [ 'comment status', 'donor comment status', 'donor_comment_status' ],
162 + 'required' => false,
163 + ],
159 164 'ip_address' => [
160 165 'label' => __( 'IP Address', 'suredonation' ),
161 166 'aliases' => [ 'ip address', 'ip', 'ip_address' ],
162 167 'required' => false,
@@ -434,8 +439,9 @@
434 439 __( 'Subscription Status', 'suredonation' ),
435 440 __( 'Parent Subscription ID', 'suredonation' ),
436 441 __( 'Anonymous', 'suredonation' ),
437 442 __( 'Donor Comment', 'suredonation' ),
443 + __( 'Comment Status', 'suredonation' ),
438 444 __( 'IP Address', 'suredonation' ),
439 445 __( 'Date', 'suredonation' ),
440 446 __( 'Import Source', 'suredonation' ),
441 447 __( 'Import Source ID', 'suredonation' ),
@@ -442,12 +448,43 @@
442 448 ];
443 449 }
444 450
445 451 /**
452 + * The trailing export column a donation's custom fields spill into once
453 + * they exceed the exporter's per-export column cap.
454 + *
455 + * Single source of truth shared with Import_Export_Api::export_donations(),
456 + * which writes this same label as a plain JSON object of label => value.
457 + * Kept separate from standard_donation_export_labels() (which the importer
458 + * treats as columns to skip entirely) because this one instead needs its
459 + * own value decoded and expanded — see extract_custom_fields().
460 + *
461 + * Deliberately untranslated: this same string is written on export and
462 + * matched on import (extract_custom_fields()), so an export made under one
463 + * site locale would fail to match on import under another, silently
464 + * storing the JSON blob as one literal field instead of expanding it —
465 + * the exact corruption this column exists to prevent. Interchange data,
466 + * not display copy, same reasoning as the anonymous yes/no export tokens.
467 + *
468 + * @return string Column label.
469 + * @since 1.6.1
470 + */
471 + public static function other_fields_export_label() {
472 + return 'Other Fields';
473 + }
474 +
475 + /**
446 476 * Pull submitted custom form-field values out of a donation row: any column
447 477 * whose header is not a standard export column is treated as a custom field
448 478 * (these are the per-form fields flattened into trailing export columns).
449 479 *
480 + * The "Other Fields" column is the one exception: it is itself a JSON object
481 + * of label => value for whatever didn't fit in the export's own column cap,
482 + * so its cell is decoded and expanded into individual fields rather than
483 + * stored verbatim as one field literally named "Other Fields" — otherwise a
484 + * re-import of a capped export would silently corrupt donation_data with a
485 + * single bogus field holding a raw JSON blob.
486 + *
450 487 * @param array<int, string> $headers CSV header cells.
451 488 * @param array<int, string> $row Raw row cells (column order).
452 489 * @return array<string, array{label: string, value: string}> Custom fields keyed by slug.
453 490 * @since 1.3.0
@@ -459,8 +496,10 @@
459 496 },
460 497 self::standard_donation_export_labels()
461 498 );
462 499
500 + $other_fields_label = strtolower( trim( self::other_fields_export_label() ) );
501 +
463 502 $fields = [];
464 503 foreach ( $headers as $index => $header ) {
465 504 $label = trim( (string) $header );
466 505 if ( '' === $label || in_array( strtolower( $label ), $standard, true ) ) {
@@ -465,12 +504,35 @@
465 504 $label = trim( (string) $header );
466 505 if ( '' === $label || in_array( strtolower( $label ), $standard, true ) ) {
467 506 continue;
468 507 }
508 +
469 509 $value = isset( $row[ $index ] ) ? (string) $row[ $index ] : '';
470 510 if ( '' === $value ) {
471 511 continue;
472 512 }
513 +
514 + if ( strtolower( $label ) === $other_fields_label ) {
515 + $overflow = json_decode( $value, true );
516 + if ( is_array( $overflow ) ) {
517 + foreach ( $overflow as $overflow_label => $overflow_value ) {
518 + $overflow_label = trim( (string) $overflow_label );
519 + if ( '' === $overflow_label || ! is_scalar( $overflow_value ) ) {
520 + continue;
521 + }
522 + $overflow_key = sanitize_key( $overflow_label );
523 + if ( '' === $overflow_key ) {
524 + continue;
525 + }
526 + $fields[ $overflow_key ] = [
527 + 'label' => sanitize_text_field( $overflow_label ),
528 + 'value' => sanitize_text_field( (string) $overflow_value ),
529 + ];
530 + }
531 + }
532 + continue;
533 + }
534 +
473 535 $key = sanitize_key( $label );
474 536 if ( '' === $key ) {
475 537 $key = 'field_' . (int) $index;
476 538 }