PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 2.21.13
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v2.21.13
V-3.3.0 3.2.2 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 V3.0.3 V3.0.2 -3.0.1 V_3.0.0 1.1.1 1.1.8 1.2 1.3 1.4 1.4.18 1.5.2 1.9 2.0 2.10.0 2.10.1 2.10.2 All 137 releases
bit-form / includes / BfAnalytics.php

BfAnalytics.php in Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder 2.21.13, at includes/BfAnalytics.php

303 lines 8.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace BitCode\BitForm;
4
5 use BitCode\BitForm\BitApps\WPTelemetry\Telemetry\Telemetry;
6
7 if (!\defined('ABSPATH')) {
8 exit;
9 }
10 class BfAnalytics
11 {
12 private $allForms;
13
14 public function __construct()
15 {
16 global $wpdb;
17 $this->allForms = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}bitforms_form"); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
18 }
19
20 public function modifyTelemetryData()
21 {
22 $bfInfo = [];
23 $formsArr = [];
24 foreach ($this->allForms as $form) {
25 $formData = [];
26 $formData['id'] = $form->id;
27 $formContent = json_decode($form->form_content, true);
28 $formData['fields'] = $this->fieldCount($formContent['fields']);
29 $formData['workflows'] = $this->countRow($form->id, 'bitforms_workflows');
30 $formData['pdfTemplate'] = $this->countRow($form->id, 'bitforms_pdf_template');
31 $formData['emailTemplate'] = $this->countRow($form->id, 'bitforms_email_template');
32 $formData['integrations'] = $this->getIntegrations($form->id);
33 $formData['formAbandonment'] = $this->getFormAbandonment($form->id);
34 $formData['doubleOptin'] = $this->getDoubleOptin($form->id);
35 $formData['tableView'] = $this->countRow($form->id, 'bitforms_frontend_views');
36 $formsArr[] = $formData;
37 }
38 $bfInfo['forms'] = $formsArr;
39 $bfInfo['totalForms'] = count($this->allForms);
40 $bfInfo['reCaptchaV3'] = $this->getReCaptchaV3();
41 $bfInfo['paymentGateway'] = $this->getPaymentGateway();
42 $bfInfo['paymentInfo'] = $this->getPaymentInfo();
43 $bfInfo['smtp'] = $this->isSMTPExist();
44
45 return $bfInfo;
46 }
47
48 public function analyticsOptIn($permission)
49 {
50 if (true === $permission) {
51 Telemetry::report()->trackingOptIn();
52 return true;
53 }
54 Telemetry::report()->trackingOptOut();
55 return false;
56 }
57
58 public function isTrackingEnabled()
59 {
60 return (bool) Telemetry::report()->isTrackingAllowed();
61 }
62
63 private function fieldCount($fields)
64 {
65 $count = [];
66 foreach ($fields as $field) {
67 if (isset($count[$field['typ']])) {
68 $count[$field['typ']]++;
69 } else {
70 $count[$field['typ']] = 1;
71 }
72 }
73 return $count;
74 }
75
76 private function countRow($formId, $tablename)
77 {
78 global $wpdb;
79 $safeTable = esc_sql($tablename);
80 $totalRow = $wpdb->get_results(
81 $wpdb->prepare(
82 "SELECT COUNT(*) as count FROM `{$wpdb->prefix}{$safeTable}` WHERE form_id = %d;",
83 $formId
84 )
85 );
86 return $totalRow[0]->count ?? 0;
87 }
88
89 private function getIntegrations($formId)
90 {
91 global $wpdb;
92 $integrations = $wpdb->get_results(
93 $wpdb->prepare(
94 "SELECT integration_type FROM `{$wpdb->prefix}bitforms_integration` WHERE form_id = %d AND category='form';",
95 $formId
96 )
97 );
98
99 $integrationNameArr = array_map(function ($integration) {
100 return $integration->integration_type;
101 }, $integrations);
102
103 return $integrationNameArr;
104 }
105
106 private function getFormAbandonment($formId)
107 {
108 global $wpdb;
109 $formAbandonment = $wpdb->get_results(
110 $wpdb->prepare(
111 "SELECT integration_details FROM `{$wpdb->prefix}bitforms_integration` WHERE form_id = %d AND category='formAbandonment';",
112 $formId
113 )
114 );
115 if (count($formAbandonment) > 0) {
116 $formAbandonment = json_decode($formAbandonment[0]->integration_details, true);
117 } else {
118 $formAbandonment = (object)[];
119 }
120 return $formAbandonment;
121 }
122
123 private function getDoubleOptin($formId)
124 {
125 global $wpdb;
126 $doubleOptin = $wpdb->get_results(
127 $wpdb->prepare(
128 "SELECT integration_details FROM `{$wpdb->prefix}bitforms_integration` WHERE category='doubleOptin' AND form_id = %d;",
129 $formId
130 )
131 );
132 if (count($doubleOptin) > 0) {
133 return true;
134 }
135 return false;
136 }
137
138 private function getIntegType($integration_type)
139 {
140 global $wpdb;
141 return $wpdb->get_results(
142 $wpdb->prepare(
143 "SELECT integration_type, integration_details FROM `{$wpdb->prefix}bitforms_integration` WHERE integration_type=%s;",
144 $integration_type
145 )
146 );
147 }
148
149 private function getReCaptchaV3()
150 {
151 $name = $this->getIntegType('gReCaptchaV3');
152 if (count($name) > 0) {
153 return true;
154 }
155 return false;
156 }
157
158 private function getPaymentGateway()
159 {
160 $types = $this->getIntegType('payments');
161
162 $paymentTypeArr = array_map(function ($type) {
163 $integration_details = json_decode($type->integration_details, true);
164 return $integration_details['type'];
165 }, $types);
166
167 return $paymentTypeArr;
168 }
169
170 private function isSMTPExist()
171 {
172 $type = $this->getIntegType('smtp');
173
174 if (count($type) > 0) {
175 return true;
176 }
177 return false;
178 }
179
180 private function getPaymentInfo()
181 {
182 if (!defined('BITFORMPRO_PLUGIN_DIR')) {
183 return [];
184 }
185
186 global $wpdb;
187
188 // Fetch all transactions
189 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
190 $allTransactions = $wpdb->get_results(
191 "SELECT * FROM `{$wpdb->prefix}bitforms_payments`;"
192 );
193
194 if (empty($allTransactions)) {
195 return [];
196 }
197
198 $result = [
199 'totalPaymentFormEntries' => 0,
200 'payments' => [],
201 'totalForm' => 0,
202 ];
203
204 $tempTotalForms = [];
205
206 foreach ($allTransactions as $trx) {
207 $gateway = strtolower($trx->payment_name);
208
209 $paymentResponse = json_decode($trx->payment_response, true) ?? [];
210
211 if (false === in_array($trx->form_id, $tempTotalForms)) {
212 $tempTotalForms[] = $trx->form_id;
213 }
214
215 // Initialize gateway
216 if (!isset($result['payments'][$gateway])) {
217 $result['payments'][$gateway] = [
218 'totalTransaction' => 0,
219 'transactionDetails' => []
220 ];
221 }
222
223 $gatewayRef = &$result['payments'][$gateway];
224
225 if (!$this->isLiveMode($gateway, $paymentResponse)) {
226 continue;
227 }
228 $gatewayRef['totalTransaction'] += 1;
229 // Determine amount and currency
230 [$amount, $currency] = $this->extractAmountAndCurrency($gateway, $paymentResponse);
231
232 // Add each transaction as a new object in the array
233 $gatewayRef['transactionDetails'][] = [
234 'amount' => $amount,
235 'currency' => $currency
236 ];
237 $result['totalPaymentFormEntries'] += 1;
238 }
239
240 $result['totalForm'] = count($tempTotalForms);
241
242 return $result;
243 }
244
245 /**
246 * Extracts amount and currency from a payment response for any gateway
247 */
248 private function extractAmountAndCurrency($gateway, $response)
249 {
250 $amount = 0;
251 $currency = 'unknown';
252
253 switch ($gateway) {
254 case 'stripe':
255 $amount = isset($response['amount']) && is_numeric($response['amount'])
256 ? $response['amount'] / 100
257 : 0;
258 $currency = strtolower($response['currency'] ?? 'usd');
259 break;
260
261 case 'razorpay':
262 $amount = isset($response['amount']) && is_numeric($response['amount'])
263 ? $response['amount'] / 100
264 : 0;
265 $currency = strtolower($response['currency'] ?? 'inr');
266 break;
267
268 case 'paypal':
269 $unit = $response['purchase_units'][0]['amount'] ?? [];
270 $amount = floatval($unit['value'] ?? 0);
271 $currency = strtolower($unit['currency_code'] ?? 'usd');
272 break;
273
274 case 'mollie':
275 $amount = floatval($response['amount']['value'] ?? 0);
276 $currency = strtolower($response['amount']['currency'] ?? 'eur');
277 break;
278 }
279
280 return [$amount, $currency];
281 }
282
283 private function isLiveMode(string $gateway, array $response): bool
284 {
285 switch ($gateway) {
286 case 'stripe':
287 return !empty($response['livemode']);
288
289 case 'razorpay':
290 return isset($response['status']) && 'captured' === $response['status'];
291
292 case 'paypal':
293 return isset($response['status']) && 'COMPLETED' === $response['status'];
294
295 case 'mollie':
296 return isset($response['mode']) && 'live' === $response['mode'];
297
298 default:
299 return false;
300 }
301 }
302 }
303