PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.29
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.29
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.29, at classes/models/FrmUsage.php

628 lines 13.6 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 ) {
202 continue;
203 }
204
205 if ( in_array( $key, $skip_keys, true ) || str_ends_with( $key, '_url' ) ) {
206 unset( $data[ $key ] );
207 continue;
208 }
209
210 if ( is_object( $value ) ) {
211 $value = '{{object}}';
212 continue;
213 }
214
215 if ( is_array( $value ) ) {
216 $this->clean_before_send( $value );
217 continue;
218 }
219
220 if ( in_array( $key, $long_text_keys, true ) || str_ends_with( $key, '_msg' ) ) {
221 // Replace it with a placeholder.
222 $value = '{{long_text}}';
223 continue;
224 }
225
226 // If key ends with `_email`, or value contains `@`, this might contain an email address.
227 if ( str_ends_with( $key, '_email' ) || str_contains( $value, '@' ) ) {
228 // Replace it with a placeholder.
229 $value = '{{contain_email}}';
230 }
231 }//end foreach
232 }
233
234 /**
235 * Gets onboarding wizard data.
236 *
237 * @since 6.16.1
238 *
239 * @return array
240 */
241 private function onboarding_wizard() {
242 $data = FrmOnboardingWizardController::get_usage_data();
243 $skipped_keys = array(
244 'default_email',
245 'is_subscribed',
246 'allows_tracking',
247 'summary_emails',
248 'installed_addons',
249 );
250
251 foreach ( $skipped_keys as $skipped_key ) {
252 unset( $data[ $skipped_key ] );
253 }
254
255 return $data;
256 }
257
258 /**
259 * Gets payments data.
260 *
261 * @since 6.16.1
262 *
263 * @param string $table Database table name.
264 *
265 * @return array
266 */
267 private function payments( $table = 'frm_payments' ) {
268 $allowed_tables = array( 'frm_payments', 'frm_subscriptions' );
269
270 if ( ! in_array( $table, $allowed_tables, true ) ) {
271 return array();
272 }
273
274 if ( ! FrmTransLiteAppHelper::payments_table_exists() ) {
275 return array();
276 }
277
278 global $wpdb;
279 $rows = $wpdb->get_results(
280 $wpdb->prepare(
281 'SELECT amount, status, paysys, created_at FROM %1$s',
282 $wpdb->prefix . $table
283 )
284 );
285
286 $payments = array();
287
288 foreach ( $rows as $row ) {
289 $payments[] = array(
290 'amount' => (float) $row->amount,
291 'status' => $row->status,
292 'gateway' => $row->paysys,
293 'created_at' => $row->created_at,
294 );
295 }
296
297 return $payments;
298 }
299
300 /**
301 * @since 3.06.04
302 *
303 * @return array
304 */
305 private function plugins() {
306 $plugin_list = FrmAppHelper::get_plugins();
307 $plugins = array();
308
309 foreach ( $plugin_list as $slug => $info ) {
310 $plugins[] = array(
311 'name' => $info['Name'],
312 'slug' => $slug,
313 'version' => $info['Version'],
314 'active' => is_plugin_active( $slug ),
315 );
316 }
317
318 return $plugins;
319 }
320
321 /**
322 * Add global settings to tracking data.
323 *
324 * @since 3.06.04
325 *
326 * @return array
327 */
328 private function settings() {
329 $settings_list = FrmAppHelper::get_settings();
330 $settings = array(
331 'messages' => $this->messages( $settings_list ),
332 'permissions' => $this->permissions( $settings_list ),
333 );
334 $pass_settings = array(
335 'load_style',
336 'fade_form',
337 're_type',
338 're_lang',
339 're_multi',
340 'menu',
341 'mu_menu',
342 'no_ips',
343 'custom_header_ip',
344 'enable_gdpr',
345 'no_gdpr_cookies',
346 'btsp_css',
347 'btsp_version',
348 'admin_bar',
349 'summary_emails',
350 'active_captcha',
351 'honeypot',
352 'wp_spam_check',
353 'denylist_check',
354 'email_style',
355 );
356
357 foreach ( $pass_settings as $setting ) {
358 if ( isset( $settings_list->$setting ) ) {
359 $settings[ $setting ] = $this->maybe_json( $settings_list->$setting );
360 }
361 }
362
363 $settings = apply_filters( 'frm_usage_settings', $settings );
364
365 $settings['messages'] = $this->maybe_json( $settings['messages'] );
366 $settings['permissions'] = $this->maybe_json( $settings['permissions'] );
367
368 return $settings;
369 }
370
371 /**
372 * Include the permissions settings for each capability.
373 *
374 * @since 3.06.04
375 *
376 * @param FrmSettings $settings_list
377 *
378 * @return array
379 */
380 private function messages( $settings_list ) {
381 $messages = array(
382 'success_msg',
383 'blank_msg',
384 'unique_msg',
385 'invalid_msg',
386 'failed_msg',
387 'submit_value',
388 'login_msg',
389 'admin_permission',
390 );
391
392 $default = $settings_list->default_options();
393 $message_settings = array();
394
395 foreach ( $messages as $message ) {
396 $message_settings[ 'changed-' . $message ] = $settings_list->$message === $default[ $message ] ? 0 : 1;
397 }
398
399 return $message_settings;
400 }
401
402 /**
403 * Include the permissions settings for each capability.
404 *
405 * @since 3.06.04
406 *
407 * @param FrmSettings $settings_list
408 *
409 * @return array
410 */
411 private function permissions( $settings_list ) {
412 $permissions = array();
413 $frm_roles = FrmAppHelper::frm_capabilities();
414
415 foreach ( $frm_roles as $frm_role => $frm_role_description ) {
416 if ( isset( $settings_list->$frm_role ) ) {
417 $permissions[ $frm_role ] = $settings_list->$frm_role;
418 }
419 }
420
421 return $permissions;
422 }
423
424 /**
425 * @since 3.06.04
426 *
427 * @return array
428 */
429 private function forms() {
430 $s_query = array(
431 array(
432 'or' => 1,
433 'parent_form_id' => null,
434 'parent_form_id <' => 1,
435 ),
436 );
437
438 $saved_forms = FrmForm::getAll( $s_query );
439 $forms = array();
440 $settings = array(
441 'form_class',
442 'akismet',
443 'antispam',
444 'stopforumspam',
445 'custom_style',
446 'success_action',
447 'show_form',
448 'no_save',
449 'ajax_load',
450 'ajax_submit',
451 'js_validate',
452 'logged_in_role',
453 'single_entry',
454 'single_entry_type',
455 'editable_role',
456 'open_editable_role',
457 'edit_action',
458 'edit_value',
459 'edit_msg',
460 'save_draft',
461 'draft_msg',
462 'submit_align',
463 'protect_files',
464 'protect_files_role',
465 'max_entries',
466 'open_status',
467 'closed_msg',
468 'open_date',
469 'close_date',
470 'copy',
471 'prev_value',
472 'submit_conditions',
473 );
474
475 $style = new FrmStyle();
476
477 foreach ( $saved_forms as $form ) {
478 $new_form = array(
479 'form_id' => $form->id,
480 'description' => $form->description,
481 'logged_in' => $form->logged_in,
482 'editable' => $form->editable,
483 'is_template' => $form->is_template,
484 'entry_count' => FrmEntry::getRecordCount( $form->id ),
485 'field_count' => $this->form_field_count( $form->id ),
486 'form_action_count' => $this->form_action_count( $form->id ),
487 );
488
489 foreach ( $settings as $setting ) {
490 if ( ! isset( $form->options[ $setting ] ) ) {
491 continue;
492 }
493
494 if ( 'custom_style' !== $setting ) {
495 $new_form[ $setting ] = $this->maybe_json( $form->options[ $setting ] );
496 continue;
497 }
498
499 $style->id = $form->options[ $setting ];
500
501 if ( ! $style->id ) {
502 $style_name = 0;
503 } elseif ( 1 === intval( $style->id ) ) {
504 $style_name = 'formidable-style';
505 } else {
506 $style_post = $style->get_one();
507 $style_name = $style_post ? $style_post->post_name : 'formidable-style';
508 }
509
510 $new_form[ $setting ] = $style_name;
511 }//end foreach
512
513 $forms[] = apply_filters( 'frm_usage_form', $new_form, compact( 'form' ) );
514 }//end foreach
515
516 // If the array uses numeric keys, reset them.
517 return $forms;
518 }
519
520 /**
521 * @since 3.06.04
522 *
523 * @param int|string $form_id Form ID.
524 *
525 * @return int
526 */
527 private function form_field_count( $form_id ) {
528 global $wpdb;
529
530 $join = $wpdb->prefix . 'frm_fields fi JOIN ' . $wpdb->prefix . 'frm_forms fo ON (fi.form_id=fo.id)';
531
532 $field_query = array(
533 'or' => 1,
534 'fi.form_id' => $form_id,
535 'parent_form_id' => $form_id,
536 );
537
538 return FrmDb::get_count( $join, $field_query );
539 }
540
541 /**
542 * @since 3.06.04
543 *
544 * @param int|string $form_id Form ID.
545 *
546 * @return int
547 */
548 private function form_action_count( $form_id ) {
549 $args = array(
550 'post_type' => FrmFormActionsController::$action_post_type,
551 'menu_order' => $form_id,
552 'fields' => 'ids',
553 );
554
555 $actions = FrmDb::check_cache( json_encode( $args ), 'frm_actions', $args, 'get_posts' );
556 return count( $actions );
557 }
558
559 /**
560 * Get the last 100 fields created.
561 *
562 * @since 3.06.04
563 *
564 * @return array
565 */
566 private function fields() {
567 $args = array(
568 'limit' => 50,
569 'order_by' => 'id DESC',
570 );
571
572 $fields = FrmDb::get_results( 'frm_fields', array(), 'id, form_id, name, type, field_options', $args );
573
574 foreach ( $fields as $k => $field ) {
575 FrmAppHelper::unserialize_or_decode( $field->field_options );
576 $fields[ $k ]->field_options = $field->field_options;
577 }
578
579 return $fields;
580 }
581
582 /**
583 * @since 3.06.04
584 *
585 * @return array
586 */
587 private function actions() {
588 $args = array(
589 'post_type' => FrmFormActionsController::$action_post_type,
590 'numberposts' => 100,
591 );
592
593 $actions = array();
594 $saved_actions = FrmDb::check_cache( json_encode( $args ), 'frm_actions', $args, 'get_posts' );
595
596 foreach ( $saved_actions as $action ) {
597 $actions[] = array(
598 'form_id' => $action->menu_order,
599 'type' => $action->post_excerpt,
600 'status' => $action->post_status,
601 'settings' => FrmAppHelper::maybe_json_decode( $action->post_content ),
602 );
603 }
604
605 return $actions;
606 }
607
608 /**
609 * @since 3.06.04
610 *
611 * @return bool
612 */
613 private function tracking_allowed() {
614 return FrmUsageController::tracking_allowed();
615 }
616
617 /**
618 * @since 3.06.04
619 *
620 * @param mixed $value Value.
621 *
622 * @return string
623 */
624 private function maybe_json( $value ) {
625 return is_array( $value ) ? json_encode( $value ) : $value;
626 }
627 }
628