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/Import.php +65 -21 2.3.4 → 2.4.1 View file →
@@ -34,8 +34,40 @@
34 34
35 35 }
36 36
37 37 /**
38 + * A CSV `payment_date` cell as the UTC `Y-m-d H:i:s` the table stores.
39 + *
40 + * The export writes the date in site time, in the site's date and time
41 + * format (`Export`: `wp_date()`), so a cell without a timezone is read as
42 + * site time and converted. It used to be stored as if it were UTC, so an
43 + * export → import round trip moved every row by the site's UTC offset. A
44 + * cell that names its own timezone (`Z`, `+06:00`, `UTC`, `GMT`) is honoured
45 + * as given. An unparseable cell keeps the old result (the epoch).
46 + *
47 + * @since 2.4.1
48 + *
49 + * @param string $value Cell value.
50 + * @return string
51 + */
52 + public static function payment_date_from_csv( $value ) {
53 + $value = trim( (string) $value );
54 + $timestamp = strtotime( $value );
55 +
56 + if ( false === $timestamp ) {
57 + return gmdate( 'Y-m-d H:i:s', 0 );
58 + }
59 +
60 + if ( preg_match( '/(?:Z|[+-]\d{2}:?\d{2}|\bUTC|\bGMT)$/i', $value ) ) {
61 + return gmdate( 'Y-m-d H:i:s', $timestamp );
62 + }
63 +
64 + // strtotime() read the wall-clock time as UTC (WordPress runs PHP in UTC);
65 + // it is site time, so convert it.
66 + return get_gmt_from_date( gmdate( 'Y-m-d H:i:s', $timestamp ), 'Y-m-d H:i:s' );
67 + }
68 +
69 + /**
38 70 * Decode a CSV `form_fields_info` cell into an array.
39 71 *
40 72 * The cell comes from an uploaded file, so it is never handed to maybe_unserialize():
41 73 * that instantiates any class a serialized payload names, which turns an import into an
@@ -103,29 +135,10 @@
103 135
104 136 $data = array();
105 137
106 138 foreach ( $records as $record ) {
107 - $better_form_fields = [
108 - 'primary_first_name' => sanitize_text_field( $record['name'] ),
109 - 'email' => sanitize_email( $record['email'] ),
110 - 'source' => sanitize_text_field( $record['source'] ),
111 - 'is_imported' => intval(1),
112 - ];
139 + $better_form_fields = $this->build_form_fields( $record );
113 140
114 - if ( ! empty( $record['payment_type'] ) && strtolower($record['payment_type']) === 'subscription' ) {
115 - $better_form_fields_selected = isset( $record['form_fields_info'] ) ? self::decode_form_fields_info( $record['form_fields_info'] ) : [];
116 -
117 - $better_form_fields['subscription_id'] = isset( $better_form_fields_selected['subscription_id'] ) ? sanitize_text_field( $better_form_fields_selected['subscription_id'] ) : '';
118 - $better_form_fields['subscription_customer_id'] = isset( $better_form_fields_selected['subscription_customer_id'] ) ? sanitize_text_field( $better_form_fields_selected['subscription_customer_id'] ) : '';
119 - $better_form_fields['subscription_plan_id'] = isset( $better_form_fields_selected['subscription_plan_id'] ) ? sanitize_text_field( $better_form_fields_selected['subscription_plan_id'] ) : '';
120 - $better_form_fields['subscription_interval'] = isset( $better_form_fields_selected['subscription_interval'] ) ? sanitize_text_field( $better_form_fields_selected['subscription_interval'] ) : '';
121 - $better_form_fields['subscription_current_period_start'] = isset( $better_form_fields_selected['subscription_current_period_start'] ) ? sanitize_text_field( $better_form_fields_selected['subscription_current_period_start'] ) : '';
122 - $better_form_fields['subscription_current_period_end'] = isset( $better_form_fields_selected['subscription_current_period_end'] ) ? sanitize_text_field( $better_form_fields_selected['subscription_current_period_end'] ) : '';
123 - $better_form_fields['subscription_status'] = isset( $better_form_fields_selected['subscription_status'] ) ? sanitize_text_field( $better_form_fields_selected['subscription_status'] ) : '';
124 - $better_form_fields['subscription_created_date'] = isset( $better_form_fields_selected['subscription_created_date'] ) ? sanitize_text_field( $better_form_fields_selected['subscription_created_date'] ) : '';
125 - $better_form_fields['is_payment_split_payment'] = isset( $better_form_fields_selected['is_payment_split_payment'] ) ? sanitize_text_field( $better_form_fields_selected['is_payment_split_payment'] ) : '';
126 - }
127 -
128 141 $amount_currency_array = explode(' ', $record['amount']);
129 142 $currency = is_array($amount_currency_array) && count($amount_currency_array) > 1 ? $amount_currency_array[0] : esc_html('USD');
130 143 $amount = is_array($amount_currency_array) && count($amount_currency_array) > 1 ? $amount_currency_array[1] : $record['amount'];
131 144
@@ -136,9 +149,9 @@
136 149 // 'payment_type' => sanitize_text_field( $record['payment_type'] ),
137 150 'transaction_id' => sanitize_text_field( $record['transaction_id'] ),
138 151 'source' => sanitize_text_field( $record['source'] ),
139 152 'status' => sanitize_text_field( $record['status'] ),
140 - 'payment_date' => date( 'Y-m-d H:i:s', strtotime( sanitize_text_field( $record['payment_date'] ) ) ),
153 + 'payment_date' => self::payment_date_from_csv( sanitize_text_field( $record['payment_date'] ) ),
141 154 'form_fields_info' => maybe_serialize( $better_form_fields ),
142 155 );
143 156 }
144 157
@@ -160,8 +173,39 @@
160 173 }
161 174
162 175 wp_safe_redirect( $_SERVER['HTTP_REFERER'] );
163 176 exit;
177 + }
178 +
179 + /**
180 + * The `form_fields_info` an imported CSV row is stored with.
181 + *
182 + * Lite keeps the name, email and source and marks the row imported.
183 + * `better_payment/import/form_fields_info` receives that, the CSV row and the
184 + * row's decoded `form_fields_info` cell: Pro adds the subscription keys of a
185 + * "Subscription" row there.
186 + *
187 + * @since 2.4.0
188 + *
189 + * @param mixed $record CSV row keyed by header; anything else is treated as empty.
190 + * @return array
191 + */
192 + public function build_form_fields( $record ) {
193 + $record = is_array( $record ) ? $record : [];
194 +
195 + $better_form_fields = [
196 + 'primary_first_name' => sanitize_text_field( $record['name'] ?? '' ),
197 + 'email' => sanitize_email( $record['email'] ?? '' ),
198 + 'source' => sanitize_text_field( $record['source'] ?? '' ),
199 + 'is_imported' => intval(1),
200 + ];
201 +
202 + // Decoded without instantiating objects; see decode_form_fields_info().
203 + $decoded = isset( $record['form_fields_info'] ) ? self::decode_form_fields_info( $record['form_fields_info'] ) : [];
204 +
205 + $filtered = apply_filters( 'better_payment/import/form_fields_info', $better_form_fields, $record, $decoded );
206 +
207 + return is_array( $filtered ) ? $filtered : $better_form_fields;
164 208 }
165 209
166 210 public function validate_csv_file( $file ){
167 211 $message = __('Invalid File!', 'better-payment');