PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.4.1
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.4.1
2.4.1 2.4.0 2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.2 2.2.1 2.2.0 2.1.2 2.1.1 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 All 68 releases
← All changes | includes/Classes/Export.php +52 -28 2.2.0 → 2.4.1 View file →
@@ -21,9 +21,19 @@
21 21 */
22 22 class Export extends Controller{
23 23
24 24 use Helper;
25 +
25 26 /**
27 + * CSV escape character, passed to fputcsv() explicitly on every call.
28 + *
29 + * PHP 8.4 deprecates relying on fputcsv()'s default $escape, because that
30 + * default will change in a later release. Passing the current default (a
31 + * backslash) keeps the output byte-identical on PHP 7.4 through 8.5.
32 + */
33 + const CSV_ESCAPE = "\\";
34 +
35 + /**
26 36 * Class constructor
27 37 *
28 38 * @since 0.0.4
29 39 */
@@ -77,9 +87,11 @@
77 87 $filter_args['status'] = sanitize_text_field($_REQUEST['status']);
78 88 }
79 89
80 90 $filter_args['per_page'] = '999999999';
81 - $all_transactions = $transaction_model->get_transactions($filter_args);
91 + // The admin list's v2 tab buckets, so an export of a tab holds exactly the rows that tab
92 + // lists. The v1 path matched `completed` against the raw status `completed` only.
93 + $all_transactions = $transaction_model->get_transactions($filter_args, 'v2');
82 94 $filename = 'better-payment-transactions-filtered-' . date('Y-m-d') . '.csv';
83 95 } else {
84 96 $all_transactions = $transaction_model->get_transactions();
85 97 $filename = 'better-payment-transactions-' . date('Y-m-d') . '.csv';
@@ -87,16 +99,28 @@
87 99
88 100 return $this->transactions_array_to_csv_download($all_transactions, $filename);
89 101 }
90 102
103 + /**
104 + * Write one CSV row. All CSV writes go through here so none can rely on the
105 + * deprecated default $escape.
106 + *
107 + * @param resource $handle Open, writable stream.
108 + * @param array $fields Row values.
109 + * @param string $delimiter Field delimiter.
110 + * @return int|false Bytes written, or false on failure.
111 + */
112 + public static function put_csv_row($handle, array $fields, $delimiter = ";") {
113 + return fputcsv($handle, $fields, $delimiter, "\"", self::CSV_ESCAPE);
114 + }
115 +
91 116 public function transactions_array_to_csv_download($array, $filename = "export.csv", $delimiter=";") {
92 - $bp_helper_obj = new ClassesHelper();
93 117 $wp_date_format = get_option('date_format');
94 118 $wp_time_format = get_option('time_format');
95 119
96 120 $f = fopen('php://memory', 'w');
97 121
98 - fputcsv($f, $this->export_transactions_heading(), $delimiter);
122 + self::put_csv_row($f, $this->export_transactions_heading(), $delimiter);
99 123
100 124 foreach ($array as $line) {
101 125 $line = (array)$line;
102 126 unset($line['id']);
@@ -107,17 +131,21 @@
107 131 // unset($line['form_fields_info']);
108 132 unset($line['referer']);
109 133
110 134
111 - $line['status'] = esc_html(ucfirst($bp_helper_obj->get_type_by_transaction_status($line['status'], 'v2')));
135 + // From the stored row (form_fields_info still serialized): an unconfirmed pre-2.4.0 free
136 + // checkout exports as Incomplete (Helper::transaction_status_type()).
137 + $line['status'] = esc_html( ClassesHelper::transaction_status_label( $line ) );
112 138 $line['source'] = esc_html( ucfirst( $line['source'] ) );
113 139 $line['payment_date'] = wp_date($wp_date_format.' '.$wp_time_format, strtotime($line['payment_date']));;
114 140
141 + // 'One Time' unless Pro labels the row (better_payment/transaction/payment_type).
142 + $line['payment_type'] = ClassesHelper::payment_type_label( maybe_unserialize( $line['form_fields_info'] ) );
143 +
115 144 $line['form_fields_info'] = $this->form_fields_info_formatted($line['form_fields_info']);
116 -
145 +
117 146 $line['form_fields_info_name'] = isset($line['form_fields_info']['customer_name']) ? $line['form_fields_info']['customer_name'] : '';
118 147 $line['form_fields_info_email'] = isset($line['form_fields_info']['customer_email']) ? $line['form_fields_info']['customer_email'] : '';
119 - $line['payment_type'] = ! empty( $line['form_fields_info']['subscription_id'] ) ? 'Subscription' : 'One Time';
120 148
121 149 unset($line['form_fields_info']['customer_name']);
122 150 unset($line['form_fields_info']['customer_email']);
123 151
@@ -136,9 +164,9 @@
136 164 $line['payment_date'],
137 165 ! empty( $line['form_fields_info'] ) ? maybe_serialize( $line['form_fields_info'] ) : '',
138 166 );
139 167
140 - fputcsv($f, $line_formatted, $delimiter);
168 + self::put_csv_row($f, $line_formatted, $delimiter);
141 169 }
142 170
143 171 // reset the file pointer to the start of the file
144 172 fseek($f, 0);
@@ -170,22 +198,21 @@
170 198 // 'Referer'
171 199 );
172 200 }
173 201
202 + /**
203 + * The fields a transaction contributes to the CSV: customer name and email, plus
204 + * whatever `better_payment/export/form_fields_info` adds.
205 + *
206 + * Pro adds the subscription keys its recurring and split checkouts store; a free
207 + * install exports name and email.
208 + *
209 + * @param mixed $form_fields_info Serialized or unserialized form_fields_info.
210 + * @return array
211 + */
174 212 public function form_fields_info_formatted($form_fields_info){
175 213 $bp_form_fields_info = maybe_unserialize($form_fields_info);
176 214
177 - $bp_transaction_subscription_id = isset($bp_form_fields_info['subscription_id']) ? sanitize_text_field($bp_form_fields_info['subscription_id']) : '';
178 - $bp_transaction_subscription_customer_id = isset($bp_form_fields_info['subscription_customer_id']) ? sanitize_text_field($bp_form_fields_info['subscription_customer_id']) : '';
179 - $bp_transaction_subscription_plan_id = isset($bp_form_fields_info['subscription_plan_id']) ? sanitize_text_field($bp_form_fields_info['subscription_plan_id']) : '';
180 -
181 - $subscription_interval = ! empty($bp_form_fields_info['subscription_interval']) ? sanitize_text_field( $bp_form_fields_info['subscription_interval'] ) : '';
182 - $subscription_current_period_start = ! empty($bp_form_fields_info['subscription_current_period_start']) ? sanitize_text_field( $bp_form_fields_info['subscription_current_period_start'] ) : '';
183 - $subscription_current_period_end = ! empty($bp_form_fields_info['subscription_current_period_end']) ? sanitize_text_field( $bp_form_fields_info['subscription_current_period_end'] ) : '';
184 - $subscription_status = ! empty($bp_form_fields_info['subscription_status']) ? sanitize_text_field( $bp_form_fields_info['subscription_status'] ) : '';
185 - $subscription_created_date = ! empty($bp_form_fields_info['subscription_created_date']) ? sanitize_text_field( $bp_form_fields_info['subscription_created_date'] ) : '';
186 - $is_payment_split_payment = ! empty($bp_form_fields_info['is_payment_split_payment']) ? intval( $bp_form_fields_info['is_payment_split_payment'] ) : 0;
187 -
188 215 $bp_transaction_customer_name = isset($bp_form_fields_info['primary_first_name']) ? sanitize_text_field($bp_form_fields_info['primary_first_name']) : '';
189 216 $bp_transaction_customer_name .= ' ';
190 217 $bp_transaction_customer_name .= isset($bp_form_fields_info['primary_last_name']) ? sanitize_text_field($bp_form_fields_info['primary_last_name']) : '';
191 218
@@ -201,20 +228,17 @@
201 228 if( empty($bp_transaction_customer_email) ){
202 229 $bp_transaction_customer_email = isset($bp_form_fields_info['email']) ? sanitize_text_field($bp_form_fields_info['email']) : '';
203 230 }
204 231
205 - return [
232 + $formatted = [
206 233 'customer_name' => $bp_transaction_customer_name,
207 234 'customer_email' => $bp_transaction_customer_email,
208 - 'subscription_id' => $bp_transaction_subscription_id,
209 - 'subscription_customer_id' => $bp_transaction_subscription_customer_id,
210 - 'subscription_plan_id' => $bp_transaction_subscription_plan_id,
211 - 'subscription_interval' => $subscription_interval,
212 - 'subscription_current_period_start' => $subscription_current_period_start,
213 - 'subscription_current_period_end' => $subscription_current_period_end,
214 - 'subscription_status' => $subscription_status,
215 - 'subscription_created_date' => $subscription_created_date,
216 - 'is_payment_split_payment' => $is_payment_split_payment,
217 235 ];
236 +
237 + $raw_fields = is_array( $bp_form_fields_info ) ? $bp_form_fields_info : [];
238 +
239 + $filtered = apply_filters( 'better_payment/export/form_fields_info', $formatted, $raw_fields );
240 +
241 + return is_array( $filtered ) ? $filtered : $formatted;
218 242 }
219 243
220 244 }