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

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