| @@ -121,20 +121,10 @@ | ||
| 121 | 121 | }, |
| 122 | 122 | ], |
| 123 | 123 | 'status' => [ |
| 124 | 124 | 'required' => true, |
| 125 | - 'type' => 'string', | |
| 126 | - // Sourced from the table's own whitelist rather than | |
| 127 | - // restated: the two lists had already drifted — suspicious | |
| 128 | - // is written on an amount mismatch and was missing here. | |
| 129 | - 'enum' => Donations::get_valid_statuses(), | |
| 130 | 125 | 'sanitize_callback' => 'sanitize_text_field', |
| 131 | - // Required for the enum to be enforced at all. An arg with | |
| 132 | - // a sanitize_callback and no validate_callback has its enum | |
| 133 | - // silently skipped (see #340), so this endpoint answered | |
| 134 | - // "updated successfully" to a status it had refused to | |
| 135 | - // write. | |
| 136 | - 'validate_callback' => 'rest_validate_request_arg', | |
| 126 | + 'enum' => [ 'pending', 'processing', 'completed', 'failed', 'refunded', 'partially_refunded', 'cancelled' ], | |
| 137 | 127 | ], |
| 138 | 128 | ], |
| 139 | 129 | ], |
| 140 | 130 | |
| @@ -160,12 +150,10 @@ | ||
| 160 | 150 | 'permission_callback' => [ $this, 'check_permissions' ], |
| 161 | 151 | 'args' => [ |
| 162 | 152 | 'action' => [ |
| 163 | 153 | 'required' => true, |
| 164 | - 'type' => 'string', | |
| 154 | + 'sanitize_callback' => 'sanitize_text_field', | |
| 165 | 155 | 'enum' => [ 'delete', 'update_status' ], |
| 166 | - 'sanitize_callback' => 'sanitize_text_field', | |
| 167 | - 'validate_callback' => 'rest_validate_request_arg', | |
| 168 | 156 | ], |
| 169 | 157 | 'ids' => [ |
| 170 | 158 | 'required' => true, |
| 171 | 159 | 'validate_callback' => static function ( $param ) { |
| @@ -172,12 +160,10 @@ | ||
| 172 | 160 | return is_array( $param ) && ! empty( $param ); |
| 173 | 161 | }, |
| 174 | 162 | ], |
| 175 | 163 | 'status' => [ |
| 176 | - 'type' => 'string', | |
| 177 | - 'enum' => Donations::get_valid_statuses(), | |
| 178 | 164 | 'sanitize_callback' => 'sanitize_text_field', |
| 179 | - 'validate_callback' => 'rest_validate_request_arg', | |
| 165 | + 'enum' => [ 'pending', 'processing', 'completed', 'failed', 'refunded', 'partially_refunded', 'cancelled' ], | |
| 180 | 166 | ], |
| 181 | 167 | ], |
| 182 | 168 | ], |
| 183 | 169 | |
| @@ -202,16 +188,10 @@ | ||
| 202 | 188 | 'sanitize_callback' => 'absint', |
| 203 | 189 | ], |
| 204 | 190 | 'refund_type' => [ |
| 205 | 191 | 'required' => true, |
| 206 | - 'type' => 'string', | |
| 192 | + 'sanitize_callback' => 'sanitize_text_field', | |
| 207 | 193 | 'enum' => [ 'full', 'partial' ], |
| 208 | - 'sanitize_callback' => 'sanitize_text_field', | |
| 209 | - // The last arg in this file carrying the #340 shape: an | |
| 210 | - // enum that reads as enforced and is not. rest_validate_ | |
| 211 | - // request_arg() reads the schema's type, so the type above | |
| 212 | - // is not decoration. | |
| 213 | - 'validate_callback' => 'rest_validate_request_arg', | |
| 214 | 194 | ], |
| 215 | 195 | 'refund_notes' => [ |
| 216 | 196 | 'sanitize_callback' => 'sanitize_textarea_field', |
| 217 | 197 | ], |
| @@ -342,12 +322,10 @@ | ||
| 342 | 322 | * @return WP_REST_Response|WP_Error Response object. |
| 343 | 323 | * @since 0.0.1 |
| 344 | 324 | */ |
| 345 | 325 | public function get_donations( $request ) { |
| 346 | - $page = $request->get_param( 'page' ) ?? 1; | |
| 347 | - // Clamp to a minimum of 1 so the total_pages calculation below can never | |
| 348 | - // divide by zero (per_page=0 would otherwise trigger a DivisionByZeroError). | |
| 349 | - $per_page = max( 1, absint( $request->get_param( 'per_page' ) ?? 20 ) ); | |
| 326 | + $page = $request->get_param( 'page' ) ?? 1; | |
| 327 | + $per_page = $request->get_param( 'per_page' ) ?? 20; | |
| 350 | 328 | $search = $request->get_param( 'search' ) ?? ''; |
| 351 | 329 | $status = $request->get_param( 'status' ) ?? 'all'; |
| 352 | 330 | $campaign = $request->get_param( 'campaign' ) ?? ''; |
| 353 | 331 | $donor = $request->get_param( 'donor' ) ?? ''; |
| @@ -375,9 +353,9 @@ | ||
| 375 | 353 | strtoupper( $order ) // using whitelist validation in the method. |
| 376 | 354 | ); |
| 377 | 355 | |
| 378 | 356 | // Get total count. |
| 379 | - $total = Donations::count_admin_list( $status, ! empty( $campaign ) ? absint( $campaign ) : 0, sanitize_text_field( $search ) ); | |
| 357 | + $total = Donations::get_total_donations_by_status( $status, ! empty( $campaign ) ? absint( $campaign ) : 0 ); | |
| 380 | 358 | } |
| 381 | 359 | |
| 382 | 360 | // Format donations data. |
| 383 | 361 | $donations = []; |
| @@ -541,9 +519,8 @@ | ||
| 541 | 519 | 'fees_covered', |
| 542 | 520 | 'donation_type', |
| 543 | 521 | 'is_anonymous', |
| 544 | 522 | 'donor_comment', |
| 545 | - 'donor_comment_status', | |
| 546 | 523 | 'payment_status', |
| 547 | 524 | 'gateway', |
| 548 | 525 | 'transaction_id', |
| 549 | 526 | ]; |
| @@ -607,39 +584,14 @@ | ||
| 607 | 584 | ); |
| 608 | 585 | } |
| 609 | 586 | |
| 610 | 587 | $old_status = $donation['payment_status'] ?? 'pending'; |
| 611 | - $updated = Donations::update_status( $donation_id, $status ); | |
| 588 | + Donations::update_status( $donation_id, $status ); | |
| 612 | 589 | |
| 613 | - // Strictly false, which is update_status() refusing the value. A 0 is | |
| 614 | - // $wpdb->update() reporting that no row changed, which cannot mean "no | |
| 615 | - // such row" here because the 404 above already proved it exists, and | |
| 616 | - // cannot mean "same status" either because update() always writes | |
| 617 | - // updated_at. Treating both as success is how a refused write looked | |
| 618 | - // like a successful one to every client. | |
| 619 | - // | |
| 620 | - // Note for anyone comparing this with bulk_action(): that path has no | |
| 621 | - // existence check, so a 0 there does mean "no such row" and is | |
| 622 | - // correctly counted as a failure. The two are not in conflict. | |
| 623 | - if ( false === $updated ) { | |
| 624 | - return new WP_Error( | |
| 625 | - 'donation_status_not_updated', | |
| 626 | - __( 'The donation status could not be updated.', 'suredonation' ), | |
| 627 | - [ 'status' => 500 ] | |
| 628 | - ); | |
| 629 | - } | |
| 630 | - | |
| 631 | 590 | // If status changed to completed, update donor stats. |
| 632 | - // | |
| 633 | - // Guarded, not plain: an admin completing a still-pending donation here | |
| 634 | - // does not stop the gateway webhook arriving for the same row later | |
| 635 | - // (Stripe retries for days), and the webhook's donor block has no | |
| 636 | - // "still pending" check of its own. Without a marker written here, that | |
| 637 | - // webhook would record the same donation a second time and double the | |
| 638 | - // donor's total, count and largest gift. | |
| 639 | 591 | if ( 'completed' !== $old_status && 'completed' === $status ) { |
| 640 | 592 | if ( ! empty( $donation['donor_id'] ) ) { |
| 641 | - Donors::record_donation_once( $donation['donor_id'], floatval( $donation['amount'] ), $donation_id ); | |
| 593 | + Donors::record_donation( $donation['donor_id'], floatval( $donation['amount'] ) ); | |
| 642 | 594 | } |
| 643 | 595 | } |
| 644 | 596 | |
| 645 | 597 | return new WP_REST_Response( |
| @@ -690,26 +642,8 @@ | ||
| 690 | 642 | public function bulk_action( $request ) { |
| 691 | 643 | $action = $request->get_param( 'action' ); |
| 692 | 644 | $ids = $request->get_param( 'ids' ); |
| 693 | 645 | |
| 694 | - if ( ! is_array( $ids ) ) { | |
| 695 | - $ids = []; | |
| 696 | - } | |
| 697 | - | |
| 698 | - // Cap bulk operations at 200 IDs per request. Each ID triggers a | |
| 699 | - // per-row SELECT + DELETE / UPDATE — an arbitrarily large array in one | |
| 700 | - // request would chew through the database serially and time out the | |
| 701 | - // response. 200 is enough headroom for any realistic admin UI | |
| 702 | - // selection; larger jobs should be split client-side (parity with the | |
| 703 | - // donors bulk-action endpoint). | |
| 704 | - if ( count( $ids ) > 200 ) { | |
| 705 | - return new WP_Error( | |
| 706 | - 'too_many_items', | |
| 707 | - __( 'Bulk actions are limited to 200 donations per request.', 'suredonation' ), | |
| 708 | - [ 'status' => 400 ] | |
| 709 | - ); | |
| 710 | - } | |
| 711 | - | |
| 712 | 646 | $success_count = 0; |
| 713 | 647 | $error_count = 0; |
| 714 | 648 | |
| 715 | 649 | foreach ( $ids as $id ) { |
| @@ -823,10 +757,9 @@ | ||
| 823 | 757 | __( 'Stripe is not connected. Please configure Stripe in settings.', 'suredonation' ), |
| 824 | 758 | [ 'status' => 400 ] |
| 825 | 759 | ); |
| 826 | 760 | } |
| 827 | - $refund_account_id = isset( $donation['stripe_account_id'] ) && is_string( $donation['stripe_account_id'] ) ? $donation['stripe_account_id'] : ''; | |
| 828 | - $refund_result = Stripe_Helper::create_refund( $transaction_id, $refund_amount, 'requested_by_customer', $refund_account_id ); | |
| 761 | + $refund_result = Stripe_Helper::create_refund( $transaction_id, $refund_amount, 'requested_by_customer' ); | |
| 829 | 762 | } |
| 830 | 763 | |
| 831 | 764 | if ( is_wp_error( $refund_result ) ) { |
| 832 | 765 | return new WP_Error( |
| @@ -1133,42 +1066,34 @@ | ||
| 1133 | 1066 | * @since 0.0.1 |
| 1134 | 1067 | */ |
| 1135 | 1068 | private function get_donation_args( $required = true ) { |
| 1136 | 1069 | return [ |
| 1137 | - 'campaign_id' => [ | |
| 1070 | + 'campaign_id' => [ | |
| 1138 | 1071 | 'required' => $required, |
| 1139 | 1072 | 'sanitize_callback' => 'absint', |
| 1140 | 1073 | ], |
| 1141 | - 'donor_name' => [ | |
| 1074 | + 'donor_name' => [ | |
| 1142 | 1075 | 'sanitize_callback' => 'sanitize_text_field', |
| 1143 | 1076 | ], |
| 1144 | - 'donor_email' => [ | |
| 1077 | + 'donor_email' => [ | |
| 1145 | 1078 | 'sanitize_callback' => 'sanitize_email', |
| 1146 | 1079 | ], |
| 1147 | - 'donor_phone' => [ | |
| 1080 | + 'donor_phone' => [ | |
| 1148 | 1081 | 'sanitize_callback' => 'sanitize_text_field', |
| 1149 | 1082 | ], |
| 1150 | - 'amount' => [ | |
| 1083 | + 'amount' => [ | |
| 1151 | 1084 | 'required' => $required, |
| 1152 | 1085 | 'sanitize_callback' => static function ( $value ) { |
| 1153 | 1086 | return floatval( $value ); |
| 1154 | 1087 | }, |
| 1155 | 1088 | ], |
| 1156 | - 'fees_covered' => [ | |
| 1089 | + 'fees_covered' => [ | |
| 1157 | 1090 | 'sanitize_callback' => static function ( $value ) { |
| 1158 | 1091 | return floatval( $value ); |
| 1159 | 1092 | }, |
| 1160 | 1093 | ], |
| 1161 | - // No 'default' on this or 'payment_status' below, deliberately. These args | |
| 1162 | - // are shared with the update route, where WordPress fills an absent param | |
| 1163 | - // with its declared default before the callback runs — so update_donation()' | |
| 1164 | - // s `! is_null()` test passes and the field is written even though the | |
| 1165 | - // client never sent it. A partial update (e.g. the Donor Comment panel | |
| 1166 | - // sending only donor_comment_status) therefore reset payment_status to | |
| 1167 | - // 'pending' and donation_type to 'one-time', un-completing the donation and | |
| 1168 | - // downgrading a subscription. create_donation() supplies its own fallbacks | |
| 1169 | - // (`?? 'pending'`, `?? 'one-time'`), so nothing depends on the defaults here. | |
| 1170 | - 'donation_type' => [ | |
| 1094 | + 'donation_type' => [ | |
| 1095 | + 'default' => 'one-time', | |
| 1171 | 1096 | 'enum' => [ 'one-time', 'recurring', 'renewal' ], |
| 1172 | 1097 | 'sanitize_callback' => 'sanitize_text_field', |
| 1173 | 1098 | 'validate_callback' => static function ( $param ) { |
| 1174 | 1099 | return in_array( $param, [ 'one-time', 'recurring', 'renewal' ], true ); |
| @@ -1173,50 +1098,28 @@ | ||
| 1173 | 1098 | 'validate_callback' => static function ( $param ) { |
| 1174 | 1099 | return in_array( $param, [ 'one-time', 'recurring', 'renewal' ], true ); |
| 1175 | 1100 | }, |
| 1176 | 1101 | ], |
| 1177 | - 'is_anonymous' => [ | |
| 1102 | + 'is_anonymous' => [ | |
| 1178 | 1103 | 'sanitize_callback' => 'rest_sanitize_boolean', |
| 1179 | 1104 | ], |
| 1180 | - 'donor_comment' => [ | |
| 1181 | - // sanitize_textarea_field, matching the capture path in | |
| 1182 | - // Payment_Helper::get_mapped_donor_comment(). wp_kses_post() was | |
| 1183 | - // actively destructive here: it parses anything tag-shaped, so a | |
| 1184 | - // moderator saving the comment "a < b and 3 > 2" stored "a <b> 2" | |
| 1185 | - // — losing " and 3 " — and any surviving markup then rendered as | |
| 1186 | - // literal angle brackets, because the campaign page esc_html()s. | |
| 1187 | - // Both sanitizers preserve the donor's newlines. | |
| 1188 | - 'sanitize_callback' => 'sanitize_textarea_field', | |
| 1105 | + 'donor_comment' => [ | |
| 1106 | + 'sanitize_callback' => 'wp_kses_post', | |
| 1189 | 1107 | ], |
| 1190 | - 'donor_comment_status' => [ | |
| 1191 | - 'enum' => [ 'approved', 'pending', 'rejected' ], | |
| 1108 | + 'payment_status' => [ | |
| 1109 | + 'default' => 'pending', | |
| 1110 | + 'enum' => [ 'pending', 'processing', 'completed', 'failed', 'refunded', 'partially_refunded', 'cancelled' ], | |
| 1192 | 1111 | 'sanitize_callback' => 'sanitize_text_field', |
| 1193 | - // A sanitize_callback silently disables `enum` enforcement, so the | |
| 1194 | - // allowed set is checked here too — otherwise any string would reach | |
| 1195 | - // the column and every comment would read as un-approved. | |
| 1196 | 1112 | 'validate_callback' => static function ( $param ) { |
| 1197 | - return in_array( $param, Donations::get_valid_comment_statuses(), true ); | |
| 1113 | + return in_array( $param, [ 'pending', 'processing', 'completed', 'failed', 'refunded', 'partially_refunded', 'cancelled' ], true ); | |
| 1198 | 1114 | }, |
| 1199 | 1115 | ], |
| 1200 | - 'payment_status' => [ | |
| 1201 | - 'type' => 'string', | |
| 1202 | - // Deliberately no 'default'. These args are shared with the | |
| 1203 | - // update route, and WordPress fills an absent param with its | |
| 1204 | - // default before the callback runs — so update_donation()'s | |
| 1205 | - // `! is_null()` test passes and the status is overwritten on a | |
| 1206 | - // partial update the client never sent it in. dev carries the | |
| 1207 | - // default; keeping it here would reinstate that bug. See | |
| 1208 | - // Test_Donations_API::test_update_donation_ignores_unsent_fields(). | |
| 1209 | - 'enum' => Donations::get_valid_statuses(), | |
| 1116 | + 'gateway' => [ | |
| 1210 | 1117 | 'sanitize_callback' => 'sanitize_text_field', |
| 1211 | - 'validate_callback' => 'rest_validate_request_arg', | |
| 1212 | 1118 | ], |
| 1213 | - 'gateway' => [ | |
| 1119 | + 'transaction_id' => [ | |
| 1214 | 1120 | 'sanitize_callback' => 'sanitize_text_field', |
| 1215 | 1121 | ], |
| 1216 | - 'transaction_id' => [ | |
| 1217 | - 'sanitize_callback' => 'sanitize_text_field', | |
| 1218 | - ], | |
| 1219 | 1122 | ]; |
| 1220 | 1123 | } |
| 1221 | 1124 | |
| 1222 | 1125 | /** |
| @@ -1242,13 +1145,12 @@ | ||
| 1242 | 1145 | * @return int Amount in smallest currency unit. |
| 1243 | 1146 | * @since 0.0.1 |
| 1244 | 1147 | */ |
| 1245 | 1148 | private function amount_to_stripe_format( $amount, $currency ) { |
| 1246 | - // Delegates rather than repeating the zero-decimal list: the abilities | |
| 1247 | - // layer guards refunds with Payment_Helper, so a second hardcoded list | |
| 1248 | - // here could disagree with the guard about what a currency's minor unit | |
| 1249 | - // is. Payment_Helper derives it from the currency data table. | |
| 1250 | - return Payment_Helper::amount_to_stripe_format( $amount, $currency ); | |
| 1149 | + $zero_decimal = [ 'BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'UGX', 'VND', 'VUV', 'XAF', 'XOF', 'XPF' ]; | |
| 1150 | + return in_array( strtoupper( $currency ), $zero_decimal, true ) | |
| 1151 | + ? (int) round( $amount ) | |
| 1152 | + : (int) round( $amount * 100 ); | |
| 1251 | 1153 | } |
| 1252 | 1154 | |
| 1253 | 1155 | /** |
| 1254 | 1156 | * Convert amount from Stripe's smallest currency unit. |
| @@ -1258,9 +1160,12 @@ | ||
| 1258 | 1160 | * @return float Amount in major currency unit. |
| 1259 | 1161 | * @since 0.0.1 |
| 1260 | 1162 | */ |
| 1261 | 1163 | private function amount_from_stripe_format( $amount, $currency ) { |
| 1262 | - return Payment_Helper::amount_from_stripe_format( $amount, $currency ); | |
| 1164 | + $zero_decimal = [ 'BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'UGX', 'VND', 'VUV', 'XAF', 'XOF', 'XPF' ]; | |
| 1165 | + return in_array( strtoupper( $currency ), $zero_decimal, true ) | |
| 1166 | + ? (float) $amount | |
| 1167 | + : (float) $amount / 100; | |
| 1263 | 1168 | } |
| 1264 | 1169 | |
| 1265 | 1170 | /** |
| 1266 | 1171 | * Format donation data for API response. |
| @@ -1293,41 +1198,14 @@ | ||
| 1293 | 1198 | if ( ! is_array( $donation_data ) ) { |
| 1294 | 1199 | $donation_data = []; |
| 1295 | 1200 | } |
| 1296 | 1201 | |
| 1297 | - // Build the persisted submitted fields list (label/value/group). The | |
| 1298 | - // group is the parent block label (e.g. "Address") used to nest | |
| 1299 | - // sub-fields on the entry screen; '' for standalone fields. | |
| 1300 | - $submitted_fields = []; | |
| 1301 | - if ( isset( $donation_data['fields'] ) && is_array( $donation_data['fields'] ) ) { | |
| 1302 | - foreach ( $donation_data['fields'] as $field ) { | |
| 1303 | - if ( ! is_array( $field ) ) { | |
| 1304 | - continue; | |
| 1305 | - } | |
| 1306 | - // sanitize_text_field (not esc_html) for REST data: the values are | |
| 1307 | - // already sanitized at write time and React escapes on render, so | |
| 1308 | - // esc_html here would double-encode (e.g. "Cats & Dogs" -> "Cats & Dogs"). | |
| 1309 | - $submitted_fields[] = [ | |
| 1310 | - 'label' => sanitize_text_field( Helper::get_string_value( $field['label'] ?? '' ) ), | |
| 1311 | - // Checkbox fields store a canonical untranslated token so the | |
| 1312 | - // stored column stays locale-stable; it is translated here, on | |
| 1313 | - // read, for the entry screen. Non-checkbox values pass through. | |
| 1314 | - 'value' => sanitize_text_field( Helper::format_checkbox_field_value( $field['value'] ?? '' ) ), | |
| 1315 | - 'group' => sanitize_text_field( Helper::get_string_value( $field['group'] ?? '' ) ), | |
| 1316 | - ]; | |
| 1317 | - } | |
| 1318 | - } | |
| 1319 | - | |
| 1320 | 1202 | return [ |
| 1321 | 1203 | 'id' => $donation_id, |
| 1322 | 1204 | 'campaign_id' => $campaign_id, |
| 1323 | - // Plain-text titles rendered by React (which escapes text nodes and does | |
| 1324 | - // not decode HTML entities). get_the_title() runs wptexturize, whose | |
| 1325 | - // default replacements are entities (e.g. " - " -> "–"), so decode | |
| 1326 | - // them here; wp_kses_post would leave the entity and it would show raw. | |
| 1327 | - 'campaign_title' => $campaign_id ? html_entity_decode( wp_strip_all_tags( (string) get_the_title( $campaign_id ) ), ENT_QUOTES, 'UTF-8' ) : '', | |
| 1205 | + 'campaign_title' => $campaign_id ? wp_kses_post( (string) get_the_title( $campaign_id ) ) : '', | |
| 1328 | 1206 | 'form_id' => $form_id, |
| 1329 | - 'form_title' => $form_id ? html_entity_decode( wp_strip_all_tags( (string) get_the_title( $form_id ) ), ENT_QUOTES, 'UTF-8' ) : '', | |
| 1207 | + 'form_title' => $form_id ? wp_kses_post( (string) get_the_title( $form_id ) ) : '', | |
| 1330 | 1208 | 'form_edit_url' => $form_edit_url, |
| 1331 | 1209 | 'donor_id' => isset( $donation['donor_id'] ) ? Helper::get_integer_value( $donation['donor_id'] ) : 0, |
| 1332 | 1210 | 'donor_name' => esc_html( Helper::get_string_value( $donation['donor_name'] ?? '' ) ), |
| 1333 | 1211 | 'donor_email' => sanitize_email( Helper::get_string_value( $donation['donor_email'] ?? '' ) ), |
| @@ -1337,18 +1215,9 @@ | ||
| 1337 | 1215 | 'refunded_amount' => Helper::get_float_value( $donation['refunded_amount'] ?? 0 ), |
| 1338 | 1216 | 'currency' => esc_html( Helper::get_string_value( $donation['currency'] ?? 'USD' ) ), |
| 1339 | 1217 | 'donation_type' => esc_html( Helper::get_string_value( $donation['donation_type'] ?? 'one-time' ) ), |
| 1340 | 1218 | 'is_anonymous' => ! empty( $donation['is_anonymous'] ), |
| 1341 | - // Returned raw, unlike its neighbours. The only consumer is the React | |
| 1342 | - // moderation panel, which renders it as a text child and so escapes it | |
| 1343 | - // itself; and DonorCommentSection writes this value straight back on | |
| 1344 | - // Save. Running it through wp_kses_post() here therefore did not | |
| 1345 | - // protect anything — it parsed anything tag-shaped and the moderator | |
| 1346 | - // persisted the parsed result, so "a < b and 3 > 2" was shown as | |
| 1347 | - // "a <b> 2" and saved as "a 2". esc_html() would be just as wrong: | |
| 1348 | - // the panel would display the entities rather than the donor's text. | |
| 1349 | - 'donor_comment' => Helper::get_string_value( $donation['donor_comment'] ?? '' ), | |
| 1350 | - 'donor_comment_status' => esc_html( Helper::get_string_value( $donation['donor_comment_status'] ?? 'approved' ) ), | |
| 1219 | + 'donor_comment' => wp_kses_post( Helper::get_string_value( $donation['donor_comment'] ?? '' ) ), | |
| 1351 | 1220 | 'payment_status' => esc_html( Helper::get_string_value( $donation['payment_status'] ?? 'pending' ) ), |
| 1352 | 1221 | 'payment_mode' => esc_html( Helper::get_string_value( $payment_mode ) ), |
| 1353 | 1222 | 'gateway' => esc_html( Helper::get_string_value( $donation['gateway'] ?? '' ) ), |
| 1354 | 1223 | 'transaction_id' => esc_html( Helper::get_string_value( $donation['transaction_id'] ?? '' ) ), |
| @@ -1357,9 +1226,8 @@ | ||
| 1357 | 1226 | 'subscription_status' => esc_html( Helper::get_string_value( $donation['subscription_status'] ?? '' ) ), |
| 1358 | 1227 | 'parent_subscription_id' => isset( $donation['parent_subscription_id'] ) ? Helper::get_integer_value( $donation['parent_subscription_id'] ) : 0, |
| 1359 | 1228 | 'subscription_interval' => esc_html( Helper::get_string_value( $donation_data['subscription_interval'] ?? '' ) ), |
| 1360 | 1229 | 'billing_cycles' => esc_html( Helper::get_string_value( $donation_data['billing_cycles'] ?? '' ) ), |
| 1361 | - 'fields' => $submitted_fields, | |
| 1362 | 1230 | 'created_at' => esc_html( Helper::get_string_value( $donation['created_at'] ?? '' ) ), |
| 1363 | 1231 | 'updated_at' => esc_html( Helper::get_string_value( $donation['updated_at'] ?? '' ) ), |
| 1364 | 1232 | 'logs' => $logs, |
| 1365 | 1233 | ]; |