PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.10
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.10
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 / controllers / FrmFormActionsController.php

FrmFormActionsController.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.10, at classes/controllers/FrmFormActionsController.php

639 lines 18.2 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 class FrmFormActionsController {
7 public static $action_post_type = 'frm_form_actions';
8 public static $registered_actions;
9
10 /**
11 * Variables saved in the post:
12 * post_content: json settings
13 * menu_order: form id
14 * post_excerpt: action type
15 */
16 public static function register_post_types() {
17 register_post_type(
18 self::$action_post_type,
19 array(
20 'label' => __( 'Form Actions', 'formidable' ),
21 'description' => '',
22 'public' => false,
23 'show_ui' => false,
24 'exclude_from_search' => true,
25 'show_in_nav_menus' => false,
26 'show_in_menu' => true,
27 'capability_type' => 'page',
28 'supports' => array( 'title', 'editor', 'excerpt', 'custom-fields', 'page-attributes' ),
29 'has_archive' => false,
30 )
31 );
32
33 self::actions_init();
34 }
35
36 public static function actions_init() {
37 self::$registered_actions = new Frm_Form_Action_Factory();
38 self::register_actions();
39 do_action( 'frm_form_actions_init' );
40 }
41
42 /**
43 * @return void
44 */
45 public static function register_actions() {
46 $action_classes = array(
47 'on_submit' => 'FrmOnSubmitAction',
48 'email' => 'FrmEmailAction',
49 'wppost' => 'FrmDefPostAction',
50 'register' => 'FrmDefRegAction',
51 'paypal' => 'FrmDefPayPalAction',
52 'payment' => 'FrmTransLiteAction',
53 'quiz' => 'FrmDefQuizAction',
54 'quiz_outcome' => 'FrmDefQuizOutcomeAction',
55 'mailchimp' => 'FrmDefMlcmpAction',
56 'api' => 'FrmDefApiAction',
57 'salesforce' => 'FrmDefSalesforceAction',
58 'activecampaign' => 'FrmDefActiveCampaignAction',
59 'constantcontact' => 'FrmDefConstContactAction',
60 'getresponse' => 'FrmDefGetResponseAction',
61 'hubspot' => 'FrmDefHubspotAction',
62 'zapier' => 'FrmDefZapierAction',
63 'twilio' => 'FrmDefTwilioAction',
64 'highrise' => 'FrmDefHighriseAction',
65 'mailpoet' => 'FrmDefMailpoetAction',
66 'aweber' => 'FrmDefAweberAction',
67 'googlespreadsheet' => 'FrmDefGoogleSpreadsheetAction',
68 );
69
70 $action_classes = apply_filters( 'frm_registered_form_actions', $action_classes );
71
72 include_once FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/email_action.php';
73 include_once FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/default_actions.php';
74
75 foreach ( $action_classes as $action_class ) {
76 self::$registered_actions->register( $action_class );
77 }
78 }
79
80 /**
81 * @since 4.0
82 *
83 * @param array $values
84 */
85 public static function email_settings( $values ) {
86 $form = FrmForm::getOne( $values['id'] );
87 $groups = self::form_action_groups();
88
89 $action_controls = self::get_form_actions();
90 self::maybe_add_action_to_group( $action_controls, $groups );
91
92 $allowed = self::active_actions( $action_controls );
93
94 include FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/settings.php';
95 }
96
97 /**
98 * Add unknown actions to a group.
99 *
100 * @since 4.0
101 */
102 private static function maybe_add_action_to_group( $action_controls, &$groups ) {
103 $grouped = array();
104 foreach ( $groups as $group ) {
105 if ( isset( $group['actions'] ) ) {
106 $grouped = array_merge( $grouped, $group['actions'] );
107 }
108 }
109
110 foreach ( $action_controls as $action ) {
111 if ( isset( $groups[ $action->id_base ] ) || in_array( $action->id_base, $grouped ) ) {
112 continue;
113 }
114
115 $this_group = $action->action_options['group'];
116 if ( ! isset( $groups[ $this_group ] ) ) {
117 $this_group = 'misc';
118 }
119
120 if ( ! isset( $groups[ $this_group ]['actions'] ) ) {
121 $groups[ $this_group ]['actions'] = array();
122 }
123 $groups[ $this_group ]['actions'][] = $action->id_base;
124
125 unset( $action );
126 }
127 }
128
129 /**
130 * @since 4.0
131 *
132 * @return array
133 */
134 public static function form_action_groups() {
135 $groups = array(
136 'misc' => array(
137 'name' => '',
138 'icon' => 'frm_icon_font frm_shuffle_icon',
139 'actions' => array(
140 'email',
141 'wppost',
142 'register',
143 'quiz',
144 'quiz_outcome',
145 'twilio',
146 ),
147 ),
148 'payment' => array(
149 'name' => __( 'eCommerce', 'formidable' ),
150 'icon' => 'frm_icon_font frm_credit_card_alt_icon',
151 'actions' => array(
152 'paypal',
153 'payment',
154 ),
155 ),
156 'marketing' => array(
157 'name' => __( 'Email Marketing', 'formidable' ),
158 'icon' => 'frm_icon_font frm_mail_bulk_icon',
159 'actions' => array(
160 'mailchimp',
161 'activecampaign',
162 'constantcontact',
163 'getresponse',
164 'aweber',
165 'mailpoet',
166 ),
167 ),
168 'crm' => array(
169 'name' => __( 'CRM', 'formidable' ),
170 'icon' => 'frm_icon_font frm_address_card_icon',
171 'actions' => array(
172 'salesforce',
173 'hubspot',
174 'highrise',
175 ),
176 ),
177 );
178
179 return apply_filters( 'frm_action_groups', $groups );
180 }
181
182 /**
183 * Get the number of currently active form actions.
184 *
185 * @since 4.0
186 *
187 * @return array
188 */
189 private static function active_actions( $action_controls ) {
190 $allowed = array();
191 foreach ( $action_controls as $action_control ) {
192 if ( isset( $action_control->action_options['active'] ) && $action_control->action_options['active'] ) {
193 $allowed[] = $action_control->id_base;
194 }
195 }
196 return $allowed;
197 }
198
199 /**
200 * For each add-on, add an li, class, and javascript function. If active, add an additional class.
201 *
202 * @since 4.0
203 * @param object $action_control
204 * @param array $allowed
205 */
206 public static function show_action_icon_link( $action_control, $allowed ) {
207 $data = array();
208 $classes = ' frm_' . $action_control->id_base . '_action frm_single_action';
209
210 $group_class = ' frm-group-' . $action_control->action_options['group'];
211
212 /* translators: %s: Name of form action */
213 $upgrade_label = sprintf( esc_html__( '%s form actions', 'formidable' ), $action_control->action_options['tooltip'] );
214
215 $default_shown = array( 'wppost', 'register', 'payment', 'quiz', 'hubspot' );
216 $default_shown = array_values( array_diff( $default_shown, $allowed ) );
217 $default_position = array_search( $action_control->id_base, $default_shown );
218 $allowed_count = count( $allowed );
219
220 if ( isset( $action_control->action_options['active'] ) && $action_control->action_options['active'] ) {
221 $classes .= ' frm_active_action';
222 } else {
223 $classes .= ' frm_inactive_action';
224 if ( $default_position !== false && ( $allowed_count + $default_position ) < 6 ) {
225 $group_class .= ' frm-default-show';
226 }
227
228 $data['data-upgrade'] = $upgrade_label;
229 $data['data-medium'] = 'settings-' . $action_control->id_base;
230
231 $upgrading = FrmAddonsController::install_link( $action_control->action_options['plugin'] );
232 if ( isset( $upgrading['url'] ) ) {
233 $data['data-oneclick'] = json_encode( $upgrading );
234 }
235
236 if ( isset( $action_control->action_options['message'] ) ) {
237 $data['data-message'] = $action_control->action_options['message'];
238 }
239
240 $requires = FrmFormsHelper::get_plan_required( $upgrading );
241 if ( $requires && 'free' !== $requires ) {
242 $data['data-requires'] = $requires;
243 }
244 }//end if
245
246 // HTML to include on the icon.
247 $icon_atts = array();
248 if ( $action_control->action_options['color'] !== 'var(--primary-700)' ) {
249 $icon_atts = array(
250 'style' => '--primary-700:' . $action_control->action_options['color'],
251 );
252 }
253
254 include FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/_action_icon.php';
255 }
256
257 /**
258 * @param string $action
259 */
260 public static function get_form_actions( $action = 'all' ) {
261 $temp_actions = self::$registered_actions;
262 if ( empty( $temp_actions ) ) {
263 self::actions_init();
264 $temp_actions = self::$registered_actions->actions;
265 } else {
266 $temp_actions = $temp_actions->actions;
267 }
268
269 $actions = array();
270
271 foreach ( $temp_actions as $a ) {
272 if ( 'all' !== $action && $a->id_base == $action ) {
273 return $a;
274 }
275
276 $actions[ $a->id_base ] = $a;
277 }
278
279 return $actions;
280 }
281
282 /**
283 * @since 2.0
284 */
285 public static function list_actions( $form, $values ) {
286 if ( empty( $form ) ) {
287 return;
288 }
289
290 /**
291 * Use this hook to migrate old settings into a new action
292 *
293 * @since 2.0
294 */
295 do_action( 'frm_before_list_actions', $form );
296
297 $filters = array(
298 'post_status' => 'all',
299 );
300 $form_actions = FrmFormAction::get_action_for_form( $form->id, 'all', $filters );
301
302 $action_controls = self::get_form_actions();
303
304 $action_map = array();
305
306 foreach ( $action_controls as $key => $control ) {
307 $action_map[ $control->id_base ] = $key;
308 }
309
310 foreach ( $form_actions as $action ) {
311 if ( ! isset( $action_map[ $action->post_excerpt ] ) ) {
312 // don't try and show settings if action no longer exists
313 continue;
314 }
315
316 self::action_control( $action, $form, $action->ID, $action_controls[ $action_map[ $action->post_excerpt ] ], $values );
317 }
318 }
319
320 public static function action_control( $form_action, $form, $action_key, $action_control, $values ) {
321 $action_control->_set( $action_key );
322
323 $use_logging = self::should_show_log_message( $form_action->post_excerpt );
324
325 include FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/form_action.php';
326 }
327
328 public static function add_form_action() {
329 FrmAppHelper::permission_check( 'frm_edit_forms' );
330 check_ajax_referer( 'frm_ajax', 'nonce' );
331
332 global $frm_vars;
333
334 $action_key = FrmAppHelper::get_param( 'list_id', '', 'post', 'absint' );
335 $action_type = FrmAppHelper::get_param( 'type', '', 'post', 'sanitize_text_field' );
336
337 $action_control = self::get_form_actions( $action_type );
338 $action_control->_set( $action_key );
339
340 $form_id = FrmAppHelper::get_param( 'form_id', '', 'post', 'absint' );
341
342 $form_action = $action_control->prepare_new( $form_id );
343 $use_logging = self::should_show_log_message( $action_type );
344
345 $values = array();
346 $form = self::fields_to_values( $form_id, $values );
347
348 include FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/form_action.php';
349 wp_die();
350 }
351
352 public static function fill_action() {
353 FrmAppHelper::permission_check( 'frm_edit_forms' );
354 check_ajax_referer( 'frm_ajax', 'nonce' );
355
356 $action_key = FrmAppHelper::get_param( 'action_id', '', 'post', 'absint' );
357 $action_type = FrmAppHelper::get_param( 'action_type', '', 'post', 'sanitize_text_field' );
358
359 $action_control = self::get_form_actions( $action_type );
360 if ( empty( $action_control ) ) {
361 wp_die();
362 }
363
364 $form_action = $action_control->get_single_action( $action_key );
365
366 $values = array();
367 $form = self::fields_to_values( $form_action->menu_order, $values );
368
369 $use_logging = self::should_show_log_message( $action_type );
370
371 include FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/_action_inside.php';
372 wp_die();
373 }
374
375 /**
376 * @since 3.06.04
377 * @return bool
378 */
379 private static function should_show_log_message( $action_type ) {
380 $logging = array( 'api', 'salesforce', 'constantcontact', 'activecampaign' );
381 return in_array( $action_type, $logging, true ) && ! function_exists( 'frm_log_autoloader' );
382 }
383
384 private static function fields_to_values( $form_id, array &$values ) {
385 $form = FrmForm::getOne( $form_id );
386
387 $values = array(
388 'fields' => array(),
389 'id' => $form->id,
390 );
391
392 $fields = FrmField::get_all_for_form( $form->id );
393 foreach ( $fields as $k => $f ) {
394 $f = (array) $f;
395 $opts = (array) $f['field_options'];
396 $f = array_merge( $opts, $f );
397 if ( ! isset( $f['post_field'] ) ) {
398 $f['post_field'] = '';
399 }
400 $values['fields'][] = $f;
401 unset( $k, $f );
402 }
403
404 return $form;
405 }
406
407 /**
408 * @param int $form_id
409 * @return void
410 */
411 public static function update_settings( $form_id ) {
412 FrmAppHelper::permission_check( 'frm_edit_forms' );
413 $process_form = FrmAppHelper::get_post_param( 'process_form', '', 'sanitize_text_field' );
414 if ( ! wp_verify_nonce( $process_form, 'process_form_nonce' ) ) {
415 $frm_settings = FrmAppHelper::get_settings();
416 $error_args = array(
417 'title' => __( 'Verification failed', 'formidable' ),
418 'body' => $frm_settings->admin_permission,
419 'cancel_url' => add_query_arg(
420 array(
421 'page' => 'formidable',
422 'frm_action' => 'settings',
423 'id' => $form_id,
424 ),
425 admin_url( 'admin.php?' )
426 ),
427 );
428 FrmAppController::show_error_modal( $error_args );
429 return;
430 }
431
432 global $wpdb;
433
434 $registered_actions = self::$registered_actions->actions;
435
436 $old_actions = FrmDb::get_col(
437 $wpdb->posts,
438 array(
439 'post_type' => self::$action_post_type,
440 'menu_order' => $form_id,
441 ),
442 'ID'
443 );
444 $new_actions = array();
445
446 foreach ( $registered_actions as $registered_action ) {
447 $action_ids = $registered_action->update_callback( $form_id );
448 if ( ! empty( $action_ids ) ) {
449 $new_actions[] = $action_ids;
450 }
451 }
452
453 // Only use array_merge if there are new actions.
454 if ( ! empty( $new_actions ) ) {
455 $new_actions = call_user_func_array( 'array_merge', $new_actions );
456 }
457 $old_actions = array_diff( $old_actions, $new_actions );
458
459 self::delete_missing_actions( $old_actions );
460
461 FrmOnSubmitHelper::save_on_submit_settings( $form_id );
462 }
463
464 public static function delete_missing_actions( $old_actions ) {
465 if ( ! empty( $old_actions ) ) {
466 foreach ( $old_actions as $old_id ) {
467 wp_delete_post( $old_id );
468 }
469 FrmDb::cache_delete_group( 'frm_actions' );
470 }
471 }
472
473 public static function trigger_create_actions( $entry_id, $form_id, $args = array() ) {
474 $filter_args = $args;
475 $filter_args['entry_id'] = $entry_id;
476 $filter_args['form_id'] = $form_id;
477
478 $event = apply_filters( 'frm_trigger_create_action', 'create', $args );
479
480 self::trigger_actions( $event, $form_id, $entry_id, 'all', $args );
481 }
482
483 /**
484 * @param string $event
485 */
486 public static function trigger_actions( $event, $form, $entry, $type = 'all', $args = array() ) {
487 $action_status = array(
488 'post_status' => 'publish',
489 );
490 $form_actions = FrmFormAction::get_action_for_form( ( is_object( $form ) ? $form->id : $form ), $type, $action_status );
491
492 if ( empty( $form_actions ) ) {
493 return;
494 }
495
496 FrmForm::maybe_get_form( $form );
497
498 $link_settings = self::get_form_actions( $type );
499 if ( 'all' != $type ) {
500 $link_settings = array( $type => $link_settings );
501 }
502
503 $stored_actions = array();
504 $action_priority = array();
505
506 if ( in_array( $event, array( 'create', 'update' ), true ) && defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
507 $this_event = 'import';
508 } else {
509 $this_event = $event;
510 }
511
512 foreach ( $form_actions as $action ) {
513
514 $skip_this_action = ! in_array( $this_event, $action->post_content['event'], true ) || FrmOnSubmitAction::$slug === $action->post_excerpt;
515 $skip_this_action = apply_filters( 'frm_skip_form_action', $skip_this_action, compact( 'action', 'entry', 'form', 'event' ) );
516 if ( $skip_this_action ) {
517 continue;
518 }
519
520 if ( ! is_object( $entry ) ) {
521 $entry = FrmEntry::getOne( $entry, true );
522 }
523
524 if ( empty( $entry ) || ( FrmEntriesHelper::DRAFT_ENTRY_STATUS === (int) $entry->is_draft && 'draft' !== $event ) ) {
525 continue;
526 }
527
528 $child_entry = ( ( is_object( $form ) && is_numeric( $form->parent_form_id ) && $form->parent_form_id ) || ( $entry && ( $entry->form_id != $form->id || $entry->parent_item_id ) ) || ( isset( $args['is_child'] ) && $args['is_child'] ) );
529
530 if ( $child_entry ) {
531 // maybe trigger actions for sub forms
532 $trigger_children = apply_filters( 'frm_use_embedded_form_actions', false, compact( 'form', 'entry' ) );
533 if ( ! $trigger_children ) {
534 continue;
535 }
536 }
537
538 // Check conditional logic.
539 $stop = FrmFormAction::action_conditions_met( $action, $entry );
540 if ( $stop ) {
541 continue;
542 }
543
544 // Store actions so they can be triggered with the correct priority.
545 $stored_actions[ $action->ID ] = $action;
546 $action_priority[ $action->ID ] = $link_settings[ $action->post_excerpt ]->action_options['priority'];
547
548 unset( $action );
549 }//end foreach
550
551 if ( ! empty( $stored_actions ) ) {
552 asort( $action_priority );
553
554 // Make sure hooks are loaded.
555 new FrmNotification();
556
557 foreach ( $action_priority as $action_id => $priority ) {
558 $action = $stored_actions[ $action_id ];
559
560 /**
561 * Allows custom form action trigger.
562 *
563 * @since 6.10
564 *
565 * @param bool $skip Skip default trigger.
566 * @param object $action Action object.
567 * @param object $entry Entry object.
568 * @param object $form Form object.
569 * @param string $event Event ('create' or 'update').
570 */
571 if ( false === apply_filters( 'frm_custom_trigger_action', false, $action, $entry, $form, $event ) ) {
572 do_action( 'frm_trigger_' . $action->post_excerpt . '_action', $action, $entry, $form, $event );
573 do_action( 'frm_trigger_' . $action->post_excerpt . '_' . $event . '_action', $action, $entry, $form );
574 }
575
576 // If post is created, get updated $entry object.
577 if ( $action->post_excerpt === 'wppost' && $event === 'create' ) {
578 $entry = FrmEntry::getOne( $entry->id, true );
579 }
580 }//end foreach
581 }//end if
582 }
583
584 public static function duplicate_form_actions( $form_id, $values, $args = array() ) {
585 if ( empty( $args['old_id'] ) ) {
586 // Continue if we know which actions to copy.
587 return;
588 }
589
590 $action_controls = self::get_form_actions();
591
592 foreach ( $action_controls as $action_control ) {
593 $action_control->duplicate_form_actions( $form_id, $args['old_id'] );
594 unset( $action_control );
595 }
596 }
597
598 public static function limit_by_type( $where ) {
599 global $frm_vars, $wpdb;
600
601 if ( ! isset( $frm_vars['action_type'] ) ) {
602 return $where;
603 }
604
605 $where .= $wpdb->prepare( ' AND post_excerpt = %s ', $frm_vars['action_type'] );
606
607 return $where;
608 }
609 }
610
611 class Frm_Form_Action_Factory {
612 public $actions = array();
613
614 public function __construct() {
615 add_action( 'frm_form_actions_init', array( $this, '_register_actions' ), 100 );
616 }
617
618 public function register( $action_class ) {
619 $this->actions[ $action_class ] = new $action_class();
620 }
621
622 public function unregister( $action_class ) {
623 if ( isset( $this->actions[ $action_class ] ) ) {
624 unset( $this->actions[ $action_class ] );
625 }
626 }
627
628 public function _register_actions() {
629 $keys = array_keys( $this->actions );
630
631 foreach ( $keys as $key ) {
632 // don't register new action if old action with the same id is already registered
633 if ( ! isset( $this->actions[ $key ] ) ) {
634 $this->actions[ $key ]->_register();
635 }
636 }
637 }
638 }
639