PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.28
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.28
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / models / FrmUsage.php

FrmUsage.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.28, at classes/models/FrmUsage.php

615 lines 13.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 /**
7 * @since 3.06.04
8 */
9 class FrmUsage {
10
11 /**
12 * @since 3.06.04
13 *
14 * @return void
15 */
16 public function send_snapshot() {
17 if ( ! $this->tracking_allowed() ) {
18 return;
19 }
20
21 $snapshot = $this->snapshot();
22 $this->clean_before_send( $snapshot );
23
24 $ep = 'aHR0cHM6Ly91c2FnZTIuZm9ybWlkYWJsZWZvcm1zLmNvbS9zbmFwc2hvdA==';
25 // $ep = base64_encode( 'http://localhost:4567/snapshot' ); // Uncomment for testing
26 $body = json_encode( $snapshot );
27
28 // Setup variable for wp_remote_request.
29 $post = array(
30 'method' => 'POST',
31 'headers' => array(
32 'Accept' => 'application/json',
33 'Content-Type' => 'application/json',
34 'Content-Length' => strlen( $body ),
35 ),
36 'body' => $body,
37 // Without this, Debug Log catches the `http_request_failed` error.
38 'timeout' => 45,
39 );
40
41 // Remove time limit to execute this function.
42 if ( function_exists( 'set_time_limit' ) ) {
43 set_time_limit( 0 );
44 }
45
46 wp_remote_request( base64_decode( $ep ), $post );
47 }
48
49 /**
50 * @since 3.06.04
51 *
52 * @param bool $regenerate
53 *
54 * @return string
55 */
56 public function uuid( $regenerate = false ) {
57 $uuid_key = 'frm-usage-uuid';
58 $uuid = get_option( $uuid_key );
59
60 if ( $regenerate || ! $uuid ) {
61 // Definitely not cryptographically secure but
62 // close enough to provide a unique id
63 $uuid = md5( uniqid() . site_url() );
64 update_option( $uuid_key, $uuid, false );
65 }
66
67 return $uuid;
68 }
69
70 /**
71 * @since 3.06.04
72 *
73 * @return array
74 */
75 public function snapshot() {
76 global $wpdb, $wp_version;
77
78 $theme_data = wp_get_theme();
79 $form_counts = FrmForm::get_count();
80
81 $snap = array(
82 'uuid' => $this->uuid(),
83 'wp_version' => $wp_version,
84 'php_version' => phpversion(),
85 'mysql_version' => $wpdb->db_version(),
86 'os' => FrmAppHelper::get_server_os(),
87 'locale' => get_locale(),
88
89 'active_license' => FrmAppHelper::pro_is_installed(),
90 'form_count' => $form_counts->published,
91 'entry_count' => FrmEntry::getRecordCount(),
92 'timestamp' => gmdate( 'c' ),
93
94 'theme_name' => is_object( $theme_data ) ? $theme_data->Name : '', // phpcs:ignore WordPress.NamingConventions
95 'plugins' => $this->plugins(),
96 'settings' => array(
97 $this->settings(),
98 ),
99 'forms' => $this->forms(),
100 'fields' => $this->fields(),
101 'actions' => $this->actions(),
102
103 'onboarding-wizard' => $this->onboarding_wizard(),
104 'welcome-tour' => FrmWelcomeTourController::get_usage_data(),
105 'flows' => FrmUsageController::get_flows_data(),
106 'payments' => $this->payments(),
107 'subscriptions' => $this->payments( 'frm_subscriptions' ),
108 );
109
110 if ( method_exists( 'FrmProAddonsController', 'get_readable_license_type' ) ) {
111 $snap['active_license'] = FrmProAddonsController::get_readable_license_type();
112 }
113
114 return apply_filters( 'frm_usage_snapshot', $snap );
115 }
116
117 /**
118 * Cleans the snapshot data before sending.
119 *
120 * @param array $data Snapshot data.
121 *
122 * @return void
123 */
124 private function clean_before_send( &$data ) {
125 $skip_keys = array(
126 'plan_id',
127 'paypal_item_name',
128 'account_num',
129 'routing_num',
130 'bank_name',
131 'business_email',
132
133 // Form action settings.
134 'quiz',
135 'email_to',
136 'cc',
137 'bcc',
138 'from',
139 'email_subject',
140 'email_msg',
141 'email_message',
142 'success_msg',
143 'success_url',
144 'success_page_id',
145 'redirect_msg',
146 'conditions',
147 'list_id',
148 'api_key',
149 'url',
150 'data_fields',
151 'reg_email_msg',
152
153 // Form settings.
154 'form_id',
155 'description',
156 'submit_conditions-hide_field',
157 'submit_conditions-hide_field_cond',
158 'submit_conditions-hide_opt',
159 'submit_conditions-show_hide',
160 'submit_conditions-any_all',
161
162 // Field settings.
163 'show_hide',
164 'any_all',
165 'hide_field',
166 'hide_field_cond',
167 'hide_opt',
168 'custom_html',
169 'blank',
170 'required_indicator',
171 'invalid',
172 'unique_msg',
173 'edit_text',
174 'start_over_label',
175 'add_label',
176 'remove_label',
177 'draft',
178 );
179
180 /**
181 * Filter the keys to skip when cleaning the snapshot data before sending.
182 *
183 * @since 6.28
184 *
185 * @param array $skip_keys Data keys.
186 */
187 $skip_keys = apply_filters( 'frm_usage_skip_keys', $skip_keys );
188
189 $long_text_keys = array( 'description' );
190
191 /**
192 * Filter the keys to replace with a long text placeholder before sending.
193 *
194 * @since 6.28
195 *
196 * @paramm array $long_text_keys Data keys.
197 */
198 $long_text_keys = apply_filters( 'frm_usage_long_text_keys', $long_text_keys );
199
200 foreach ( $data as $key => &$value ) {
201 if ( ! $value || in_array( $key, $skip_keys, true ) || str_ends_with( $key, '_url' ) ) {
202 continue;
203 }
204
205 if ( is_array( $value ) ) {
206 $this->clean_before_send( $value );
207 continue;
208 }
209
210 if ( in_array( $key, $long_text_keys, true ) || str_ends_with( $key, '_msg' ) ) {
211 // Replace it with a placeholder.
212 $value = '{{long_text}}';
213 continue;
214 }
215
216 // If key ends with `_email`, or value contains `@`, this might contain an email address.
217 if ( str_ends_with( $key, '_email' ) || str_contains( $value, '@' ) ) {
218 // Replace it with a placeholder.
219 $value = '{{contain_email}}';
220 }
221 }//end foreach
222 }
223
224 /**
225 * Gets onboarding wizard data.
226 *
227 * @since 6.16.1
228 *
229 * @return array
230 */
231 private function onboarding_wizard() {
232 $data = FrmOnboardingWizardController::get_usage_data();
233 $skipped_keys = array(
234 'default_email',
235 'is_subscribed',
236 'allows_tracking',
237 'summary_emails',
238 'installed_addons',
239 );
240
241 foreach ( $skipped_keys as $skipped_key ) {
242 unset( $data[ $skipped_key ] );
243 }
244
245 return $data;
246 }
247
248 /**
249 * Gets payments data.
250 *
251 * @since 6.16.1
252 *
253 * @param string $table Database table name.
254 *
255 * @return array
256 */
257 private function payments( $table = 'frm_payments' ) {
258 $allowed_tables = array( 'frm_payments', 'frm_subscriptions' );
259
260 if ( ! in_array( $table, $allowed_tables, true ) ) {
261 return array();
262 }
263
264 if ( ! FrmTransLiteAppHelper::payments_table_exists() ) {
265 return array();
266 }
267
268 global $wpdb;
269 $rows = $wpdb->get_results(
270 $wpdb->prepare(
271 'SELECT amount, status, paysys, created_at FROM %1$s',
272 $wpdb->prefix . $table
273 )
274 );
275
276 $payments = array();
277
278 foreach ( $rows as $row ) {
279 $payments[] = array(
280 'amount' => (float) $row->amount,
281 'status' => $row->status,
282 'gateway' => $row->paysys,
283 'created_at' => $row->created_at,
284 );
285 }
286
287 return $payments;
288 }
289
290 /**
291 * @since 3.06.04
292 *
293 * @return array
294 */
295 private function plugins() {
296 $plugin_list = FrmAppHelper::get_plugins();
297 $plugins = array();
298
299 foreach ( $plugin_list as $slug => $info ) {
300 $plugins[] = array(
301 'name' => $info['Name'],
302 'slug' => $slug,
303 'version' => $info['Version'],
304 'active' => is_plugin_active( $slug ),
305 );
306 }
307
308 return $plugins;
309 }
310
311 /**
312 * Add global settings to tracking data.
313 *
314 * @since 3.06.04
315 *
316 * @return array
317 */
318 private function settings() {
319 $settings_list = FrmAppHelper::get_settings();
320 $settings = array(
321 'messages' => $this->messages( $settings_list ),
322 'permissions' => $this->permissions( $settings_list ),
323 );
324 $pass_settings = array(
325 'load_style',
326 'fade_form',
327 're_type',
328 're_lang',
329 're_multi',
330 'menu',
331 'mu_menu',
332 'no_ips',
333 'custom_header_ip',
334 'enable_gdpr',
335 'no_gdpr_cookies',
336 'btsp_css',
337 'btsp_version',
338 'admin_bar',
339 'summary_emails',
340 'active_captcha',
341 'honeypot',
342 'wp_spam_check',
343 'denylist_check',
344 'email_style',
345 );
346
347 foreach ( $pass_settings as $setting ) {
348 if ( isset( $settings_list->$setting ) ) {
349 $settings[ $setting ] = $this->maybe_json( $settings_list->$setting );
350 }
351 }
352
353 $settings = apply_filters( 'frm_usage_settings', $settings );
354
355 $settings['messages'] = $this->maybe_json( $settings['messages'] );
356 $settings['permissions'] = $this->maybe_json( $settings['permissions'] );
357
358 return $settings;
359 }
360
361 /**
362 * Include the permissions settings for each capability.
363 *
364 * @since 3.06.04
365 *
366 * @param FrmSettings $settings_list
367 *
368 * @return array
369 */
370 private function messages( $settings_list ) {
371 $messages = array(
372 'success_msg',
373 'blank_msg',
374 'unique_msg',
375 'invalid_msg',
376 'failed_msg',
377 'submit_value',
378 'login_msg',
379 'admin_permission',
380 );
381
382 $default = $settings_list->default_options();
383 $message_settings = array();
384
385 foreach ( $messages as $message ) {
386 $message_settings[ 'changed-' . $message ] = $settings_list->$message === $default[ $message ] ? 0 : 1;
387 }
388
389 return $message_settings;
390 }
391
392 /**
393 * Include the permissions settings for each capability.
394 *
395 * @since 3.06.04
396 *
397 * @param FrmSettings $settings_list
398 *
399 * @return array
400 */
401 private function permissions( $settings_list ) {
402 $permissions = array();
403 $frm_roles = FrmAppHelper::frm_capabilities();
404
405 foreach ( $frm_roles as $frm_role => $frm_role_description ) {
406 if ( isset( $settings_list->$frm_role ) ) {
407 $permissions[ $frm_role ] = $settings_list->$frm_role;
408 }
409 }
410
411 return $permissions;
412 }
413
414 /**
415 * @since 3.06.04
416 *
417 * @return array
418 */
419 private function forms() {
420 $s_query = array(
421 array(
422 'or' => 1,
423 'parent_form_id' => null,
424 'parent_form_id <' => 1,
425 ),
426 );
427
428 $saved_forms = FrmForm::getAll( $s_query );
429 $forms = array();
430 $settings = array(
431 'form_class',
432 'akismet',
433 'antispam',
434 'stopforumspam',
435 'custom_style',
436 'success_action',
437 'show_form',
438 'no_save',
439 'ajax_load',
440 'ajax_submit',
441 'js_validate',
442 'logged_in_role',
443 'single_entry',
444 'single_entry_type',
445 'editable_role',
446 'open_editable_role',
447 'edit_action',
448 'edit_value',
449 'edit_msg',
450 'save_draft',
451 'draft_msg',
452 'submit_align',
453 'protect_files',
454 'protect_files_role',
455 'max_entries',
456 'open_status',
457 'closed_msg',
458 'open_date',
459 'close_date',
460 'copy',
461 'prev_value',
462 'submit_conditions',
463 );
464
465 $style = new FrmStyle();
466
467 foreach ( $saved_forms as $form ) {
468 $new_form = array(
469 'form_id' => $form->id,
470 'description' => $form->description,
471 'logged_in' => $form->logged_in,
472 'editable' => $form->editable,
473 'is_template' => $form->is_template,
474 'entry_count' => FrmEntry::getRecordCount( $form->id ),
475 'field_count' => $this->form_field_count( $form->id ),
476 'form_action_count' => $this->form_action_count( $form->id ),
477 );
478
479 foreach ( $settings as $setting ) {
480 if ( isset( $form->options[ $setting ] ) ) {
481 if ( 'custom_style' === $setting ) {
482 $style->id = $form->options[ $setting ];
483
484 if ( ! $style->id ) {
485 $style_name = 0;
486 } elseif ( 1 === intval( $style->id ) ) {
487 $style_name = 'formidable-style';
488 } else {
489 $style_post = $style->get_one();
490 $style_name = $style_post ? $style_post->post_name : 'formidable-style';
491 }
492
493 $new_form[ $setting ] = $style_name;
494 } else {
495 $new_form[ $setting ] = $this->maybe_json( $form->options[ $setting ] );
496 }
497 }
498 }
499
500 $forms[] = apply_filters( 'frm_usage_form', $new_form, compact( 'form' ) );
501 }//end foreach
502
503 // If the array uses numeric keys, reset them.
504 return $forms;
505 }
506
507 /**
508 * @since 3.06.04
509 *
510 * @param int|string $form_id Form ID.
511 *
512 * @return int
513 */
514 private function form_field_count( $form_id ) {
515 global $wpdb;
516
517 $join = $wpdb->prefix . 'frm_fields fi JOIN ' . $wpdb->prefix . 'frm_forms fo ON (fi.form_id=fo.id)';
518
519 $field_query = array(
520 'or' => 1,
521 'fi.form_id' => $form_id,
522 'parent_form_id' => $form_id,
523 );
524
525 return FrmDb::get_count( $join, $field_query );
526 }
527
528 /**
529 * @since 3.06.04
530 *
531 * @param int|string $form_id Form ID.
532 *
533 * @return int
534 */
535 private function form_action_count( $form_id ) {
536 $args = array(
537 'post_type' => FrmFormActionsController::$action_post_type,
538 'menu_order' => $form_id,
539 'fields' => 'ids',
540 );
541
542 $actions = FrmDb::check_cache( json_encode( $args ), 'frm_actions', $args, 'get_posts' );
543 return count( $actions );
544 }
545
546 /**
547 * Get the last 100 fields created.
548 *
549 * @since 3.06.04
550 *
551 * @return array
552 */
553 private function fields() {
554 $args = array(
555 'limit' => 50,
556 'order_by' => 'id DESC',
557 );
558
559 $fields = FrmDb::get_results( 'frm_fields', array(), 'id, form_id, name, type, field_options', $args );
560
561 foreach ( $fields as $k => $field ) {
562 FrmAppHelper::unserialize_or_decode( $field->field_options );
563 $fields[ $k ]->field_options = $field->field_options;
564 }
565
566 return $fields;
567 }
568
569 /**
570 * @since 3.06.04
571 *
572 * @return array
573 */
574 private function actions() {
575 $args = array(
576 'post_type' => FrmFormActionsController::$action_post_type,
577 'numberposts' => 100,
578 );
579
580 $actions = array();
581 $saved_actions = FrmDb::check_cache( json_encode( $args ), 'frm_actions', $args, 'get_posts' );
582
583 foreach ( $saved_actions as $action ) {
584 $actions[] = array(
585 'form_id' => $action->menu_order,
586 'type' => $action->post_excerpt,
587 'status' => $action->post_status,
588 'settings' => FrmAppHelper::maybe_json_decode( $action->post_content ),
589 );
590 }
591
592 return $actions;
593 }
594
595 /**
596 * @since 3.06.04
597 *
598 * @return bool
599 */
600 private function tracking_allowed() {
601 return FrmUsageController::tracking_allowed();
602 }
603
604 /**
605 * @since 3.06.04
606 *
607 * @param mixed $value Value.
608 *
609 * @return string
610 */
611 private function maybe_json( $value ) {
612 return is_array( $value ) ? json_encode( $value ) : $value;
613 }
614 }
615