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/api/donations-api.php +26 -1 1.6.0 → 1.6.1 View file →
@@ -11,8 +11,9 @@
11 11 use SureDonation\Inc\Database\Tables\Donors;
12 12 use SureDonation\Inc\Emails\Email_Handler;
13 13 use SureDonation\Inc\Helper;
14 14 use SureDonation\Inc\Payments\Payment_Helper;
15 +use SureDonation\Inc\Pdf\Receipt_Generator;
15 16 use SureDonation\Inc\Payments\Stripe\Stripe_Helper;
16 17 use WP_Error;
17 18 use WP_REST_Request;
18 19 use WP_REST_Response;
@@ -663,8 +664,29 @@
663 664
664 665 $result = Donations::delete( $donation_id );
665 666
666 667 if ( ! $result ) {
668 + // A donation is kept, deliberately, when its receipt PDF could not
669 + // be removed, so that the pointer stays reachable for a retry
670 + // instead of the file being orphaned. That reads as an unexplained
671 + // failure unless it is named: the admin has to fix the filesystem,
672 + // not retry.
673 + //
674 + // Ask the helper again rather than inferring from the surviving
675 + // pointer. It is idempotent and reports whether a file is still
676 + // there, so this is the fact rather than a guess: a row whose
677 + // DELETE failed after its receipt was already removed would
678 + // otherwise be reported as an uploads-permissions problem.
679 + $donation = Donations::get( $donation_id );
680 +
681 + if ( is_array( $donation ) && ! Receipt_Generator::delete_receipt( Helper::get_string_value( $donation['receipt_pdf_url'] ?? '' ) ) ) {
682 + return new WP_Error(
683 + 'receipt_delete_failed',
684 + __( 'This donation was kept because its PDF receipt could not be removed from the uploads folder. Deleting the record on its own would leave the receipt behind. Check the permissions on the uploads folder, then try again.', 'suredonation' ),
685 + [ 'status' => 500 ]
686 + );
687 + }
688 +
667 689 return new WP_Error(
668 690 'delete_failed',
669 691 __( 'Failed to delete donation.', 'suredonation' ),
670 692 [ 'status' => 500 ]
@@ -1298,9 +1320,9 @@
1298 1320 // group is the parent block label (e.g. "Address") used to nest
1299 1321 // sub-fields on the entry screen; '' for standalone fields.
1300 1322 $submitted_fields = [];
1301 1323 if ( isset( $donation_data['fields'] ) && is_array( $donation_data['fields'] ) ) {
1302 - foreach ( $donation_data['fields'] as $field ) {
1324 + foreach ( $donation_data['fields'] as $slug => $field ) {
1303 1325 if ( ! is_array( $field ) ) {
1304 1326 continue;
1305 1327 }
1306 1328 // sanitize_text_field (not esc_html) for REST data: the values are
@@ -1306,8 +1328,11 @@
1306 1328 // sanitize_text_field (not esc_html) for REST data: the values are
1307 1329 // already sanitized at write time and React escapes on render, so
1308 1330 // esc_html here would double-encode (e.g. "Cats & Dogs" -> "Cats & Dogs").
1309 1331 $submitted_fields[] = [
1332 + // The stored key. Labels are admin-editable and translatable;
1333 + // an add-on that presents a group its own way matches on this.
1334 + 'slug' => sanitize_text_field( Helper::get_string_value( $slug ) ),
1310 1335 'label' => sanitize_text_field( Helper::get_string_value( $field['label'] ?? '' ) ),
1311 1336 // Checkbox fields store a canonical untranslated token so the
1312 1337 // stored column stays locale-stable; it is translated here, on
1313 1338 // read, for the entry screen. Non-checkbox values pass through.