PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.3.4
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.3.4
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 1.0.5 1.0.6 All 66 releases
better-payment / includes / Classes / Import.php

Import.php in Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More 2.3.4, at includes/Classes/Import.php

209 lines 9.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Better_Payment\Lite\Classes;
4
5 use Better_Payment\Lite\Admin\DB;
6 use Better_Payment\Lite\Controller;
7 use Better_Payment\Lite\Models\TransactionModel;
8 use Better_Payment\Lite\Traits\Helper;
9 use Exception;
10 use League\Csv\Reader;
11 use League\Csv\Statement;
12
13 /**
14 * Exit if accessed directly
15 */
16 if (!defined('ABSPATH')) {
17 exit;
18 }
19
20 /**
21 * Export handler class
22 *
23 * @since 0.0.4
24 */
25 class Import extends Controller{
26
27 use Helper;
28 /**
29 * Class constructor
30 *
31 * @since 0.0.4
32 */
33 public function __construct() {
34
35 }
36
37 /**
38 * Decode a CSV `form_fields_info` cell into an array.
39 *
40 * The cell comes from an uploaded file, so it is never handed to maybe_unserialize():
41 * that instantiates any class a serialized payload names, which turns an import into an
42 * object-injection sink for whatever gadget chain the site's plugins happen to provide.
43 * Objects are refused outright; only a plain array survives.
44 *
45 * @since 2.3.4
46 *
47 * @param mixed $value Cell value.
48 * @return array
49 */
50 public static function decode_form_fields_info( $value ) {
51 if ( ! is_string( $value ) || ! is_serialized( $value ) ) {
52 return [];
53 }
54
55 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize, WordPress.PHP.NoSilencedErrors.Discouraged -- classes are disallowed; a malformed cell is expected input.
56 $decoded = @unserialize( trim( $value ), [ 'allowed_classes' => false ] );
57
58 return is_array( $decoded ) ? $decoded : [];
59 }
60
61 public function import_transactions() {
62 $message = __('Invalid File!', 'better-payment');
63
64 $invalid_nonce = ! wp_verify_nonce( $_REQUEST['nonce'], 'better_payment_transaction_import_nonce' );
65 $invalid_access = ! current_user_can('manage_options') || ! isset( $_FILES['better-payment-transaction-import-input'] );
66
67 if ( $invalid_nonce || $invalid_access ) {
68 set_transient('better_payment_import_transactions_error', esc_html( $message ), 30);
69 wp_safe_redirect( $_SERVER['HTTP_REFERER'] );
70 exit;
71 }
72
73 $file = $_FILES['better-payment-transaction-import-input'];
74
75 try {
76 $this->validate_csv_file($file);
77 $csv = Reader::createFromPath($file['tmp_name'], 'r');
78 $csv->setHeaderOffset(0);
79
80 // Header validation
81 $csvHeader = $csv->getHeader();
82 if ( isset( $csvHeader[0] ) && false !== strpos( $csvHeader[0], ';' ) ) {
83 $csv->setDelimiter(';');
84 $csvHeader = $csv->getHeader();
85 }
86
87 if ( ! is_array( $csvHeader ) || ! count( $csvHeader) ){
88 throw new Exception( $message );
89 }
90
91 $csvHeader = array_map('sanitize_text_field', $csvHeader);
92
93 $exportObj = new Export();
94 $allowedHeaders = $exportObj->export_transactions_heading();
95
96 if ( count( $allowedHeaders ) !== count( $csvHeader ) ) {
97 throw new Exception( $message );
98 }
99
100 // Fetch rows
101 $stmt = Statement::create()->offset(0)->limit(3000);
102 $records = $stmt->process($csv);
103
104 $data = array();
105
106 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 ];
113
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 $amount_currency_array = explode(' ', $record['amount']);
129 $currency = is_array($amount_currency_array) && count($amount_currency_array) > 1 ? $amount_currency_array[0] : esc_html('USD');
130 $amount = is_array($amount_currency_array) && count($amount_currency_array) > 1 ? $amount_currency_array[1] : $record['amount'];
131
132 $data[] = array(
133 'email' => sanitize_email( $record['email'] ),
134 'currency' => sanitize_text_field( $currency ),
135 'amount' => floatval( $amount ),
136 // 'payment_type' => sanitize_text_field( $record['payment_type'] ),
137 'transaction_id' => sanitize_text_field( $record['transaction_id'] ),
138 'source' => sanitize_text_field( $record['source'] ),
139 'status' => sanitize_text_field( $record['status'] ),
140 'payment_date' => date( 'Y-m-d H:i:s', strtotime( sanitize_text_field( $record['payment_date'] ) ) ),
141 'form_fields_info' => maybe_serialize( $better_form_fields ),
142 );
143 }
144
145 if ( empty( $data ) ) {
146 throw new Exception( __('No valid records found in the CSV file!', 'better-payment') );
147 }
148
149 $table = DB::get_table_name();
150 $rowsInserted = $this->bulk_insert_transactions( $table, $data );
151 if ( $rowsInserted !== false && $rowsInserted > 0 ) {
152 set_transient('better_payment_import_transactions_success', esc_html__( $rowsInserted . ' rows inserted successfully!', 'better-payment' ), 30);
153 } else {
154 throw new Exception( __('Failed to insert records into database!', 'better-payment') );
155 }
156 } catch (\Exception $exception) {
157 set_transient('better_payment_import_transactions_error', esc_html( $exception->getMessage() ), 30);
158 wp_safe_redirect( $_SERVER['HTTP_REFERER'] );
159 exit;
160 }
161
162 wp_safe_redirect( $_SERVER['HTTP_REFERER'] );
163 exit;
164 }
165
166 public function validate_csv_file( $file ){
167 $message = __('Invalid File!', 'better-payment');
168
169 if ( empty( $file ) ){
170 throw new Exception( $message );
171 }
172
173 $extension = pathinfo( $file['name'], PATHINFO_EXTENSION );
174 $allowed_extensions = ['csv'];
175
176 if ( empty( $extension ) || ! in_array( $extension, $allowed_extensions ) ) {
177 throw new Exception( $message );
178 }
179
180 return true;
181 }
182
183 public function bulk_insert_transactions($table, $rows) {
184 global $wpdb;
185
186 $headers = array_keys($rows[0]);
187 asort($headers);
188 $columnList = '`' . implode('`, `', $headers) . '`';
189
190 $sql = "INSERT INTO `$table` ($columnList) VALUES\n";
191 $placeholders = array();
192 $data = array();
193
194 foreach ($rows as $row) {
195 ksort($row);
196 $rowPlaceholders = array();
197 foreach ($row as $value) {
198 $data[] = $value;
199 $rowPlaceholders[] = is_numeric($value) ? '%d' : '%s';
200 }
201 $placeholders[] = '(' . implode(', ', $rowPlaceholders) . ')';
202 }
203
204 $sql .= implode(",\n", $placeholders);
205
206 $rowsInserted = $wpdb->query($wpdb->prepare($sql, $data));
207 return $rowsInserted;
208 }
209 }