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

647 lines 18.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 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 /**
480 * @since 2.0.23
481 * @since 6.11.2 $filter_args is now passed instead of $args. It includes additional ID data.
482 *
483 * @param string $event 'create' by default. Pro may filter this value to 'draft' instead.
484 * @param array $filter_args
485 */
486 $event = apply_filters( 'frm_trigger_create_action', 'create', $filter_args );
487
488 self::trigger_actions( $event, $form_id, $entry_id, 'all', $args );
489 }
490
491 /**
492 * @param string $event
493 */
494 public static function trigger_actions( $event, $form, $entry, $type = 'all', $args = array() ) {
495 $action_status = array(
496 'post_status' => 'publish',
497 );
498 $form_actions = FrmFormAction::get_action_for_form( ( is_object( $form ) ? $form->id : $form ), $type, $action_status );
499
500 if ( empty( $form_actions ) ) {
501 return;
502 }
503
504 FrmForm::maybe_get_form( $form );
505
506 $link_settings = self::get_form_actions( $type );
507 if ( 'all' != $type ) {
508 $link_settings = array( $type => $link_settings );
509 }
510
511 $stored_actions = array();
512 $action_priority = array();
513
514 if ( in_array( $event, array( 'create', 'update' ), true ) && defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
515 $this_event = 'import';
516 } else {
517 $this_event = $event;
518 }
519
520 foreach ( $form_actions as $action ) {
521
522 $skip_this_action = ! in_array( $this_event, $action->post_content['event'], true ) || FrmOnSubmitAction::$slug === $action->post_excerpt;
523 $skip_this_action = apply_filters( 'frm_skip_form_action', $skip_this_action, compact( 'action', 'entry', 'form', 'event' ) );
524 if ( $skip_this_action ) {
525 continue;
526 }
527
528 if ( ! is_object( $entry ) ) {
529 $entry = FrmEntry::getOne( $entry, true );
530 }
531
532 if ( empty( $entry ) || ( FrmEntriesHelper::DRAFT_ENTRY_STATUS === (int) $entry->is_draft && 'draft' !== $event ) ) {
533 continue;
534 }
535
536 $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'] ) );
537
538 if ( $child_entry ) {
539 // maybe trigger actions for sub forms
540 $trigger_children = apply_filters( 'frm_use_embedded_form_actions', false, compact( 'form', 'entry' ) );
541 if ( ! $trigger_children ) {
542 continue;
543 }
544 }
545
546 // Check conditional logic.
547 $stop = FrmFormAction::action_conditions_met( $action, $entry );
548 if ( $stop ) {
549 continue;
550 }
551
552 // Store actions so they can be triggered with the correct priority.
553 $stored_actions[ $action->ID ] = $action;
554 $action_priority[ $action->ID ] = $link_settings[ $action->post_excerpt ]->action_options['priority'];
555
556 unset( $action );
557 }//end foreach
558
559 if ( ! empty( $stored_actions ) ) {
560 asort( $action_priority );
561
562 // Make sure hooks are loaded.
563 new FrmNotification();
564
565 foreach ( $action_priority as $action_id => $priority ) {
566 $action = $stored_actions[ $action_id ];
567
568 /**
569 * Allows custom form action trigger.
570 *
571 * @since 6.10
572 *
573 * @param bool $skip Skip default trigger.
574 * @param object $action Action object.
575 * @param object $entry Entry object.
576 * @param object $form Form object.
577 * @param string $event Event ('create' or 'update').
578 */
579 if ( false === apply_filters( 'frm_custom_trigger_action', false, $action, $entry, $form, $event ) ) {
580 do_action( 'frm_trigger_' . $action->post_excerpt . '_action', $action, $entry, $form, $event );
581 do_action( 'frm_trigger_' . $action->post_excerpt . '_' . $event . '_action', $action, $entry, $form );
582 }
583
584 // If post is created, get updated $entry object.
585 if ( $action->post_excerpt === 'wppost' && $event === 'create' ) {
586 $entry = FrmEntry::getOne( $entry->id, true );
587 }
588 }//end foreach
589 }//end if
590 }
591
592 public static function duplicate_form_actions( $form_id, $values, $args = array() ) {
593 if ( empty( $args['old_id'] ) ) {
594 // Continue if we know which actions to copy.
595 return;
596 }
597
598 $action_controls = self::get_form_actions();
599
600 foreach ( $action_controls as $action_control ) {
601 $action_control->duplicate_form_actions( $form_id, $args['old_id'] );
602 unset( $action_control );
603 }
604 }
605
606 public static function limit_by_type( $where ) {
607 global $frm_vars, $wpdb;
608
609 if ( ! isset( $frm_vars['action_type'] ) ) {
610 return $where;
611 }
612
613 $where .= $wpdb->prepare( ' AND post_excerpt = %s ', $frm_vars['action_type'] );
614
615 return $where;
616 }
617 }
618
619 class Frm_Form_Action_Factory {
620 public $actions = array();
621
622 public function __construct() {
623 add_action( 'frm_form_actions_init', array( $this, '_register_actions' ), 100 );
624 }
625
626 public function register( $action_class ) {
627 $this->actions[ $action_class ] = new $action_class();
628 }
629
630 public function unregister( $action_class ) {
631 if ( isset( $this->actions[ $action_class ] ) ) {
632 unset( $this->actions[ $action_class ] );
633 }
634 }
635
636 public function _register_actions() {
637 $keys = array_keys( $this->actions );
638
639 foreach ( $keys as $key ) {
640 // don't register new action if old action with the same id is already registered
641 if ( ! isset( $this->actions[ $key ] ) ) {
642 $this->actions[ $key ]->_register();
643 }
644 }
645 }
646 }
647