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

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