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
← All changes | classes/controllers/FrmFormActionsController.php +93 -658 6.346.16 View file →
@@ -3,16 +3,12 @@
3 3 die( 'You are not allowed to call this page directly.' );
4 4 }
5 5
6 6 class FrmFormActionsController {
7 -
8 - /**
9 - * @var string
10 - */
11 7 public static $action_post_type = 'frm_form_actions';
12 8
13 9 /**
14 - * @var Frm_Form_Action_Factory|null
10 + * @var array|null
15 11 */
16 12 public static $registered_actions;
17 13
18 14 /**
@@ -37,9 +33,8 @@
37 33 'has_archive' => false,
38 34 )
39 35 );
40 36
41 - self::maybe_setup_unlicensed_action_gate();
42 37 self::actions_init();
43 38 }
44 39
45 40 public static function actions_init() {
@@ -54,122 +49,49 @@
54 49 public static function register_actions() {
55 50 $action_classes = array(
56 51 'on_submit' => 'FrmOnSubmitAction',
57 52 'email' => 'FrmEmailAction',
58 - 'gated_content' => 'FrmGatedContentAction',
59 53 'wppost' => 'FrmDefPostAction',
60 54 'register' => 'FrmDefRegAction',
61 - 'stripe' => 'FrmStripeLiteAction',
62 - 'square' => 'FrmSquareAction',
63 - 'paypal' => 'FrmPayPalLiteAction',
64 - 'paypal-legacy' => 'FrmDefPayPalLegacyAction',
55 + 'paypal' => 'FrmDefPayPalAction',
65 56 'payment' => 'FrmTransLiteAction',
66 57 'quiz' => 'FrmDefQuizAction',
67 58 'quiz_outcome' => 'FrmDefQuizOutcomeAction',
59 + 'mailchimp' => 'FrmDefMlcmpAction',
68 60 'api' => 'FrmDefApiAction',
69 - 'mailchimp' => 'FrmDefMlcmpAction',
61 + 'salesforce' => 'FrmDefSalesforceAction',
70 62 'activecampaign' => 'FrmDefActiveCampaignAction',
71 63 'constantcontact' => 'FrmDefConstContactAction',
72 64 'getresponse' => 'FrmDefGetResponseAction',
65 + 'hubspot' => 'FrmDefHubspotAction',
66 + 'zapier' => 'FrmDefZapierAction',
67 + 'twilio' => 'FrmDefTwilioAction',
68 + 'highrise' => 'FrmDefHighriseAction',
73 69 'mailpoet' => 'FrmDefMailpoetAction',
70 + 'aweber' => 'FrmDefAweberAction',
74 71 'convertkit' => 'FrmDefConvertKitAction',
75 - 'aweber' => 'FrmDefAweberAction',
76 - 'twilio' => 'FrmDefTwilioAction',
77 - 'salesforce' => 'FrmDefSalesforceAction',
78 - 'hubspot' => 'FrmDefHubspotAction',
79 - 'highrise' => 'FrmDefHighriseAction',
80 - 'zapier' => 'FrmDefZapierAction',
81 72 'googlespreadsheet' => 'FrmDefGoogleSpreadsheetAction',
82 - 'n8n' => 'FrmDefN8NAction',
83 73 );
84 74
85 75 $action_classes = apply_filters( 'frm_registered_form_actions', $action_classes );
86 - $action_classes = self::maybe_unset_highrise( $action_classes );
87 76
88 77 include_once FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/email_action.php';
89 78 include_once FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/default_actions.php';
90 79
91 - // This needs to be called after we include default_actions.php or FrmDefPayPalLegacyAction will never exist.
92 - if ( 'FrmPayPalLiteAction' === $action_classes['paypal'] || ! class_exists( 'FrmPaymentAction' ) || ! class_exists( 'FrmDefPayPalLegacyAction' ) ) {
93 - unset( $action_classes['paypal-legacy'] );
94 - }
95 -
96 80 foreach ( $action_classes as $action_class ) {
97 81 self::$registered_actions->register( $action_class );
98 82 }
99 -
100 - self::apply_default_action_descriptions();
101 83 }
102 84
103 85 /**
104 - * Sets default descriptions on registered actions from a central list.
105 - *
106 - * Keeps the description when an add-on replaces a base action class without its own.
107 - *
108 - * @since 6.31
109 - *
110 - * @return void
111 - */
112 - private static function apply_default_action_descriptions() {
113 - $descriptions = array(
114 - 'on_submit' => __( 'Success messages', 'formidable' ),
115 - 'email' => __( 'Autoresponder alerts', 'formidable' ),
116 - 'wppost' => __( 'Content publishing', 'formidable' ),
117 - 'register' => __( 'Account creation', 'formidable' ),
118 - 'payment' => __( 'Transaction alerts', 'formidable' ),
119 - 'stripe' => __( 'Payment gateway', 'formidable' ),
120 - 'square' => __( 'Payment gateway', 'formidable' ),
121 - 'paypal' => __( 'Payment gateway', 'formidable' ),
122 - 'quiz' => __( 'Automated grading', 'formidable' ),
123 - 'quiz_outcome' => __( 'Result logic', 'formidable' ),
124 - 'aweber' => __( 'List triggers', 'formidable' ),
125 - 'mailchimp' => __( 'Subscription confirmation', 'formidable' ),
126 - 'zapier' => __( 'App automation', 'formidable' ),
127 - 'n8n' => __( 'Workflow automation', 'formidable' ),
128 - 'twilio' => __( 'Text notifications', 'formidable' ),
129 - 'activecampaign' => __( 'Contact automation', 'formidable' ),
130 - 'salesforce' => __( 'Lead automation', 'formidable' ),
131 - 'constantcontact' => __( 'Content distribution', 'formidable' ),
132 - 'getresponse' => __( 'Success notifications', 'formidable' ),
133 - 'hubspot' => __( 'CRM alerts', 'formidable' ),
134 - 'mailpoet' => __( 'Plugin automation', 'formidable' ),
135 - 'api' => __( 'System integration', 'formidable' ),
136 - 'googlespreadsheet' => __( 'Spreadsheet sync', 'formidable' ),
137 - 'convertkit' => __( 'Broadcast publishing', 'formidable' ),
138 - 'gated_content' => __( 'Access control', 'formidable' ),
139 - );
140 -
141 - foreach ( self::$registered_actions->actions as $action ) {
142 - if ( $action->action_options['description'] === '' && isset( $descriptions[ $action->id_base ] ) ) {
143 - $action->action_options['description'] = $descriptions[ $action->id_base ];
144 - }
145 - }
146 - }
147 -
148 - /**
149 - * Remove the Highrise action if it is not registered.
150 - *
151 - * @since 6.23
152 - *
153 - * @param array $action_classes
154 - *
155 - * @return array
156 - */
157 - private static function maybe_unset_highrise( $action_classes ) {
158 - if ( 'FrmDefHighriseAction' === ( $action_classes['highrise'] ?? '' ) ) {
159 - unset( $action_classes['highrise'] );
160 - }
161 - return $action_classes;
162 - }
163 -
164 - /**
165 86 * @since 4.0
166 87 *
167 88 * @param array $values
168 89 */
169 90 public static function email_settings( $values ) {
170 - $form = FrmForm::getOne( $values['id'] );
171 - $groups = self::form_action_groups();
91 + $form = FrmForm::getOne( $values['id'] );
92 + $groups = self::form_action_groups();
93 +
172 94 $action_controls = self::get_form_actions();
173 95 self::maybe_add_action_to_group( $action_controls, $groups );
174 96
175 97 $allowed = self::active_actions( $action_controls );
@@ -180,41 +102,23 @@
180 102 /**
181 103 * Add unknown actions to a group.
182 104 *
183 105 * @since 4.0
184 - *
185 - * @param array $action_controls
186 - * @param array $groups
187 - *
188 - * @return void
189 106 */
190 107 private static function maybe_add_action_to_group( $action_controls, &$groups ) {
191 108 $grouped = array();
192 -
193 109 foreach ( $groups as $group ) {
194 110 if ( isset( $group['actions'] ) ) {
195 111 $grouped = array_merge( $grouped, $group['actions'] );
196 112 }
197 -
198 - // Also collect actions from sections
199 - if ( ! isset( $group['sections'] ) ) {
200 - continue;
201 - }
202 -
203 - foreach ( $group['sections'] as $section ) {
204 - if ( isset( $section['actions'] ) ) {
205 - $grouped = array_merge( $grouped, $section['actions'] );
206 - }
207 - }
208 113 }
209 114
210 115 foreach ( $action_controls as $action ) {
211 - if ( isset( $groups[ $action->id_base ] ) || in_array( $action->id_base, $grouped, true ) ) {
116 + if ( isset( $groups[ $action->id_base ] ) || in_array( $action->id_base, $grouped ) ) {
212 117 continue;
213 118 }
214 119
215 120 $this_group = $action->action_options['group'];
216 -
217 121 if ( ! isset( $groups[ $this_group ] ) ) {
218 122 $this_group = 'misc';
219 123 }
220 124
@@ -232,48 +136,32 @@
232 136 *
233 137 * @return array
234 138 */
235 139 public static function form_action_groups() {
236 - // Get all action controls to check which are active
237 - $action_controls = self::get_form_actions();
238 -
239 - // Determine which actions are currently available
240 - $available_actions = self::get_available_my_actions( $action_controls );
241 -
242 - // Featured actions are add-ons that are NOT currently available
243 - $all_addon_actions = array(
244 - 'api',
245 - 'register',
246 - 'n8n',
247 - 'quiz',
248 - 'quiz_outcome',
249 - 'googlespreadsheet',
250 - );
251 - $featured_actions = array_diff( $all_addon_actions, $available_actions );
252 -
253 140 $groups = array(
254 - 'my_actions' => array(
255 - 'name' => __( 'My Actions', 'formidable' ),
256 - 'icon' => 'frmfont frm_shuffle_icon',
257 - 'sections' => array(
258 - 'active' => array(
259 - 'name' => '',
260 - 'actions' => $available_actions,
261 - ),
262 - 'featured' => array(
263 - 'name' => __( 'Featured', 'formidable' ),
264 - 'actions' => array_values( $featured_actions ),
265 - ),
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',
266 151 ),
267 152 ),
268 - 'payment' => array(
269 - 'name' => __( 'E-Commerce', 'formidable' ),
270 - 'icon' => 'frmfont frm_credit_card_alt_icon',
271 - 'actions' => self::get_payment_actions( $action_controls ),
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 + ),
272 160 ),
273 - 'marketing' => array(
274 - 'name' => __( 'Marketing', 'formidable' ),
275 - 'icon' => 'frmfont frm_mail_bulk_icon',
161 + 'marketing' => array(
162 + 'name' => __( 'Email Marketing', 'formidable' ),
163 + 'icon' => 'frm_icon_font frm_mail_bulk_icon',
276 164 'actions' => array(
277 165 'mailchimp',
278 166 'activecampaign',
279 167 'constantcontact',
@@ -279,22 +167,19 @@
279 167 'constantcontact',
280 168 'getresponse',
281 169 'aweber',
282 170 'mailpoet',
283 - 'convertkit',
284 - 'twilio',
285 171 ),
286 172 ),
287 - 'crm' => array(
173 + 'crm' => array(
288 174 'name' => __( 'CRM', 'formidable' ),
289 - 'icon' => 'frmfont frm_address_card_icon',
290 - 'actions' => self::get_crm_actions(),
175 + 'icon' => 'frm_icon_font frm_address_card_icon',
176 + 'actions' => array(
177 + 'salesforce',
178 + 'hubspot',
179 + 'highrise',
180 + ),
291 181 ),
292 - 'misc' => array(
293 - 'name' => __( 'Misc', 'formidable' ),
294 - 'icon' => 'frmfont frm_shuffle_icon',
295 - 'actions' => self::get_misc_actions( $action_controls ),
296 - ),
297 182 );
298 183
299 184 return apply_filters( 'frm_action_groups', $groups );
300 185 }
@@ -299,142 +184,21 @@
299 184 return apply_filters( 'frm_action_groups', $groups );
300 185 }
301 186
302 187 /**
303 - * Get the actions that are currently available (active) for My Actions section.
304 - *
305 - * @since 6.31
306 - *
307 - * @param array $action_controls The registered action controls.
308 - *
309 - * @return array
310 - */
311 - private static function get_available_my_actions( $action_controls ) {
312 - $available = array(
313 - 'on_submit',
314 - 'email',
315 - 'stripe',
316 - 'square',
317 - 'paypal',
318 - );
319 -
320 - // Include all actions that are marked as active, including custom actions.
321 - // This ensures custom actions appear in "My Actions" when enabled.
322 - foreach ( $action_controls as $action_id => $action_control ) {
323 - if ( ! in_array( $action_id, $available, true ) && ! empty( $action_control->action_options['active'] ) ) {
324 - $available[] = $action_id;
325 - }
326 - }
327 -
328 - return $available;
329 - }
330 -
331 - /**
332 - * Get the actions to include in the Misc section.
333 - *
334 - * @since 6.31
335 - *
336 - * @param array $action_controls The registered action controls.
337 - *
338 - * @return array
339 - */
340 - private static function get_misc_actions( $action_controls ) {
341 - $misc_actions = array(
342 - 'on_submit',
343 - 'email',
344 - 'wppost',
345 - 'register',
346 - 'api',
347 - 'n8n',
348 - 'quiz',
349 - 'quiz_outcome',
350 - 'googlespreadsheet',
351 - );
352 -
353 - // Include all active actions that aren't in specific groups (payment, marketing, crm).
354 - // This ensures custom actions appear in "Misc" when enabled.
355 - $payment_actions = self::get_payment_actions( $action_controls );
356 - $marketing_actions = array( 'mailchimp', 'activecampaign', 'constantcontact', 'getresponse', 'aweber', 'mailpoet', 'convertkit', 'twilio' );
357 -
358 - $excluded_actions = array_merge( $payment_actions, $marketing_actions, self::get_crm_actions() );
359 -
360 - foreach ( $action_controls as $action_id => $action_control ) {
361 - if ( ! in_array( $action_id, $misc_actions, true ) && ! in_array( $action_id, $excluded_actions, true ) && ! empty( $action_control->action_options['active'] ) ) {
362 - $misc_actions[] = $action_id;
363 - }
364 - }
365 -
366 - return $misc_actions;
367 - }
368 -
369 - /**
370 - * Get the actions to include in the E-Commerce section.
371 - *
372 - * @since 6.33
373 - *
374 - * @param array $action_controls
375 - *
376 - * @return array
377 - */
378 - private static function get_payment_actions( $action_controls ) {
379 - $payment_actions = array(
380 - 'paypal',
381 - 'stripe',
382 - 'square',
383 - );
384 -
385 - if ( isset( $action_controls['paypal-legacy'] ) ) {
386 - $payment_actions[] = 'paypal-legacy';
387 - }
388 -
389 - if ( isset( $action_controls['payment'] ) ) {
390 - $payment_actions[] = 'payment';
391 - }
392 -
393 - return $payment_actions;
394 - }
395 -
396 - /**
397 - * Get the actions to include in the CRM section.
398 - *
399 - * @since 6.23
400 - *
401 - * @return array
402 - */
403 - private static function get_crm_actions() {
404 - $crm_actions = array(
405 - 'salesforce',
406 - 'hubspot',
407 - 'zapier',
408 - );
409 -
410 - // Only include Highrise when the add-on is active.
411 - // This is because Highrise is deprecated. We don't want to show it in Lite.
412 - if ( class_exists( 'FrmHrsSettings' ) ) {
413 - $crm_actions[] = 'highrise';
414 - }
415 -
416 - return $crm_actions;
417 - }
418 -
419 - /**
420 188 * Get the number of currently active form actions.
421 189 *
422 190 * @since 4.0
423 191 *
424 - * @param array $action_controls
425 - *
426 192 * @return array
427 193 */
428 194 private static function active_actions( $action_controls ) {
429 195 $allowed = array();
430 -
431 196 foreach ( $action_controls as $action_control ) {
432 - if ( ! empty( $action_control->action_options['active'] ) ) {
197 + if ( isset( $action_control->action_options['active'] ) && $action_control->action_options['active'] ) {
433 198 $allowed[] = $action_control->id_base;
434 199 }
435 200 }
436 -
437 201 return $allowed;
438 202 }
439 203
440 204 /**
@@ -440,15 +204,15 @@
440 204 /**
441 205 * For each add-on, add an li, class, and javascript function. If active, add an additional class.
442 206 *
443 207 * @since 4.0
444 - *
445 208 * @param object $action_control
446 209 * @param array $allowed
447 210 */
448 211 public static function show_action_icon_link( $action_control, $allowed ) {
449 - $data = array();
450 - $classes = ' frm_' . $action_control->id_base . '_action frm_single_action';
212 + $data = array();
213 + $classes = ' frm_' . $action_control->id_base . '_action frm_single_action';
214 +
451 215 $group_class = ' frm-group-' . $action_control->action_options['group'];
452 216
453 217 /* translators: %s: Name of form action */
454 218 $upgrade_label = sprintf( esc_html__( '%s form actions', 'formidable' ), $action_control->action_options['tooltip'] );
@@ -454,20 +218,15 @@
454 218 $upgrade_label = sprintf( esc_html__( '%s form actions', 'formidable' ), $action_control->action_options['tooltip'] );
455 219
456 220 $default_shown = array( 'wppost', 'register', 'payment', 'quiz', 'hubspot' );
457 221 $default_shown = array_values( array_diff( $default_shown, $allowed ) );
458 - $default_position = array_search( $action_control->id_base, $default_shown, true );
222 + $default_position = array_search( $action_control->id_base, $default_shown );
459 223 $allowed_count = count( $allowed );
460 224
461 - if ( ! empty( $action_control->action_options['active'] ) ) {
225 + if ( isset( $action_control->action_options['active'] ) && $action_control->action_options['active'] ) {
462 226 $classes .= ' frm_active_action';
463 227 } else {
464 228 $classes .= ' frm_inactive_action';
465 -
466 - if ( str_contains( $action_control->action_options['classes'], 'frm_show_expired_modal' ) ) {
467 - $classes .= ' frm_show_expired_modal';
468 - }
469 -
470 229 if ( $default_position !== false && ( $allowed_count + $default_position ) < 6 ) {
471 230 $group_class .= ' frm-default-show';
472 231 }
473 232
@@ -474,9 +233,8 @@
474 233 $data['data-upgrade'] = $upgrade_label;
475 234 $data['data-medium'] = 'settings-' . $action_control->id_base;
476 235
477 236 $upgrading = FrmAddonsController::install_link( $action_control->action_options['plugin'] );
478 -
479 237 if ( isset( $upgrading['url'] ) ) {
480 238 $data['data-oneclick'] = json_encode( $upgrading );
481 239 }
482 240
@@ -484,67 +242,41 @@
484 242 $data['data-message'] = $action_control->action_options['message'];
485 243 }
486 244
487 245 $requires = FrmFormsHelper::get_plan_required( $upgrading );
488 -
489 246 if ( $requires && 'free' !== $requires ) {
490 247 $data['data-requires'] = $requires;
491 248 }
492 -
493 - $learn_more_slug = ! empty( $action_control->action_options['learn-more'] )
494 - ? $action_control->action_options['learn-more']
495 - : self::get_learn_more_slug( $action_control->id_base );
496 -
497 - if ( $learn_more_slug ) {
498 - $data['data-learn-more'] = FrmAppHelper::get_doc_url(
499 - $learn_more_slug,
500 - 'settings-' . $action_control->id_base,
501 - ! str_contains( $learn_more_slug, '/' )
502 - );
503 - }
504 249 }//end if
505 250
506 - include FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/_action_icon.php';
507 - }
508 -
509 - /**
510 - * Get the HTML attributes for the action icon.
511 - *
512 - * @since 6.31
513 - *
514 - * @param object $action_control
515 - *
516 - * @return array
517 - */
518 - public static function get_action_icon_atts( $action_control ) {
519 - if ( 'var(--primary-700)' !== $action_control->action_options['color'] ) {
520 - return array(
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(
521 255 'style' => '--primary-700:' . $action_control->action_options['color'],
522 256 );
523 257 }
524 258
525 - return array();
259 + include FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/_action_icon.php';
526 260 }
527 261
528 262 /**
529 263 * @param string $action
530 - *
531 264 * @return array|FrmFormAction A single form action is returned when a specific $action value is requested.
532 265 */
533 266 public static function get_form_actions( $action = 'all' ) {
534 267 $temp_actions = self::$registered_actions;
535 -
536 - if ( $temp_actions ) {
537 - $temp_actions = $temp_actions->actions;
538 - } else {
268 + if ( empty( $temp_actions ) ) {
539 269 self::actions_init();
540 270 $temp_actions = self::$registered_actions->actions;
271 + } else {
272 + $temp_actions = $temp_actions->actions;
541 273 }
542 274
543 275 $actions = array();
544 276
545 277 foreach ( $temp_actions as $a ) {
546 - if ( 'all' !== $action && $a->id_base === $action ) {
278 + if ( 'all' !== $action && $a->id_base == $action ) {
547 279 return $a;
548 280 }
549 281
550 282 $actions[ $a->id_base ] = $a;
@@ -554,16 +286,11 @@
554 286 }
555 287
556 288 /**
557 289 * @since 2.0
558 - *
559 - * @param object $form
560 - * @param array $values
561 - *
562 - * @return void
563 290 */
564 291 public static function list_actions( $form, $values ) {
565 - if ( ! $form ) {
292 + if ( empty( $form ) ) {
566 293 return;
567 294 }
568 295
569 296 /**
@@ -588,17 +315,11 @@
588 315 foreach ( $action_controls as $key => $control ) {
589 316 $action_map[ $control->id_base ] = $key;
590 317 }
591 318
592 - self::maybe_show_limit_warning( $form->id, $form_actions );
593 -
594 - echo '<p class="frm-mb-lg frm-no-actions-message' . ( $form_actions ? ' frm_hidden' : '' ) . '"> '
595 - . esc_html__( 'No actions have been added yet. Select an action above to get started.', 'formidable' )
596 - . '</p>';
597 -
598 319 foreach ( $form_actions as $action ) {
599 320 if ( ! isset( $action_map[ $action->post_excerpt ] ) ) {
600 - // Don't try and show settings if action no longer exists
321 + // don't try and show settings if action no longer exists
601 322 continue;
602 323 }
603 324
604 325 self::action_control( $action, $form, $action->ID, $action_controls[ $action_map[ $action->post_excerpt ] ], $values );
@@ -604,54 +325,8 @@
604 325 self::action_control( $action, $form, $action->ID, $action_controls[ $action_map[ $action->post_excerpt ] ], $values );
605 326 }
606 327 }
607 328
608 - /**
609 - * Show a warning before the form actions list if there are 99 actions, and the limit is set to 99.
610 - * If it is filtered, the warning is still shown when applicable, just using the new limit.
611 - *
612 - * @since 6.17
613 - *
614 - * @param int|string $form_id
615 - * @param array $form_actions
616 - *
617 - * @return void
618 - */
619 - private static function maybe_show_limit_warning( $form_id, $form_actions ) {
620 - $count = count( $form_actions );
621 -
622 - if ( $count < 99 ) {
623 - return;
624 - }
625 -
626 - $limit = FrmFormAction::get_action_limit( $form_id );
627 -
628 - if ( $limit < 99 || $count < $limit ) {
629 - return;
630 - }
631 -
632 - $documentation_url = 'https://formidableforms.com/knowledgebase/frm_form_action_limit/#kb-increase-limit-of-form-actions';
633 -
634 - echo '<div class="frm_warning_style">';
635 - FrmAppHelper::icon_by_class( 'frmfont frm_alert_icon' );
636 - echo '&nbsp;';
637 - printf(
638 - // translators: %s: URL to documentation
639 - esc_html__( 'You have reached your form action limit. To increase this limit, you will require additional code. Visit our documentation at %s.', 'formidable' ),
640 - '<a href="' . esc_url( $documentation_url ) . '" target="_blank">' . esc_html( $documentation_url ) . '</a>'
641 - );
642 - echo '</div>';
643 - }
644 -
645 - /**
646 - * @param WP_Post $form_action
647 - * @param object $form
648 - * @param int $action_key Action ID.
649 - * @param FrmFormAction $action_control
650 - * @param array $values
651 - *
652 - * @return void
653 - */
654 329 public static function action_control( $form_action, $form, $action_key, $action_control, $values ) {
655 330 $action_control->_set( $action_key );
656 331
657 332 $use_logging = self::should_show_log_message( $form_action->post_excerpt );
@@ -662,18 +337,13 @@
662 337 public static function add_form_action() {
663 338 FrmAppHelper::permission_check( 'frm_edit_forms' );
664 339 check_ajax_referer( 'frm_ajax', 'nonce' );
665 340
666 - $action_key = FrmAppHelper::get_param( 'list_id', '', 'post', 'absint' );
667 - $action_type = FrmAppHelper::get_param( 'type', '', 'post', 'sanitize_text_field' );
668 - $lite_actions = array_fill_keys( self::get_lite_actions(), true );
341 + global $frm_vars;
669 342
670 - if ( ! FrmAppHelper::pro_is_connected() && ! isset( $lite_actions[ $action_type ] ) ) {
671 - wp_die();
672 - }
343 + $action_key = FrmAppHelper::get_param( 'list_id', '', 'post', 'absint' );
344 + $action_type = FrmAppHelper::get_param( 'type', '', 'post', 'sanitize_text_field' );
673 345
674 - global $frm_vars;
675 -
676 346 /**
677 347 * @var FrmFormAction
678 348 */
679 349 $action_control = self::get_form_actions( $action_type );
@@ -678,60 +348,37 @@
678 348 */
679 349 $action_control = self::get_form_actions( $action_type );
680 350 $action_control->_set( $action_key );
681 351
682 - $form_id = FrmAppHelper::get_param( 'form_id', '', 'post', 'absint' );
683 - $form_action = $action_control->prepare_new( $form_id );
684 - $existing_titles = (array) FrmAppHelper::get_post_param( 'existing_titles', array(), 'sanitize_text_field' );
352 + $form_id = FrmAppHelper::get_param( 'form_id', '', 'post', 'absint' );
685 353
686 - if ( $existing_titles ) {
687 - $form_action->post_title = self::get_unique_action_title( $form_action->post_title, $existing_titles );
688 - }
354 + $form_action = $action_control->prepare_new( $form_id );
355 + $use_logging = self::should_show_log_message( $action_type );
689 356
690 - $use_logging = self::should_show_log_message( $action_type );
691 - $values = array();
692 - $form = self::fields_to_values( $form_id, $values );
357 + $values = array();
358 + $form = self::fields_to_values( $form_id, $values );
693 359
694 360 include FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/form_action.php';
695 361 wp_die();
696 362 }
697 363
698 - /**
699 - * Returns the first available title not in $existing_titles, appending " (2)", " (3)", etc. if needed.
700 - *
701 - * @since 6.31
702 - *
703 - * @param string $base_title Default action title from the action type.
704 - * @param string[] $existing_titles Titles currently visible in the form editor.
705 - *
706 - * @return string
707 - */
708 - private static function get_unique_action_title( $base_title, array $existing_titles ) {
709 - $taken = array_flip( $existing_titles );
710 - $title = $base_title;
711 -
712 - for ( $n = 2; isset( $taken[ $title ] ); $n++ ) {
713 - $title = $base_title . ' (' . $n . ')';
714 - }
715 -
716 - return $title;
717 - }
718 -
719 364 public static function fill_action() {
720 365 FrmAppHelper::permission_check( 'frm_edit_forms' );
721 366 check_ajax_referer( 'frm_ajax', 'nonce' );
722 367
723 - $action_key = FrmAppHelper::get_param( 'action_id', '', 'post', 'absint' );
724 - $action_type = FrmAppHelper::get_param( 'action_type', '', 'post', 'sanitize_text_field' );
368 + $action_key = FrmAppHelper::get_param( 'action_id', '', 'post', 'absint' );
369 + $action_type = FrmAppHelper::get_param( 'action_type', '', 'post', 'sanitize_text_field' );
370 +
725 371 $action_control = self::get_form_actions( $action_type );
726 -
727 - if ( ! $action_control ) {
372 + if ( empty( $action_control ) ) {
728 373 wp_die();
729 374 }
730 375
731 376 $form_action = $action_control->get_single_action( $action_key );
732 - $values = array();
733 - $form = self::fields_to_values( $form_action->menu_order, $values );
377 +
378 + $values = array();
379 + $form = self::fields_to_values( $form_action->menu_order, $values );
380 +
734 381 $use_logging = self::should_show_log_message( $action_type );
735 382
736 383 include FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/_action_inside.php';
737 384 wp_die();
@@ -738,40 +385,15 @@
738 385 }
739 386
740 387 /**
741 388 * @since 3.06.04
742 - *
743 - * @param string $action_type
744 - *
745 389 * @return bool
746 390 */
747 391 private static function should_show_log_message( $action_type ) {
748 - $logging = array(
749 - 'activecampaign',
750 - 'api',
751 - 'aweber',
752 - 'campaignmonitor',
753 - 'constantcontact',
754 - 'convertkit',
755 - 'getresponse',
756 - 'googlespreadsheet',
757 - 'hubspot',
758 - 'mailchimp',
759 - 'mailpoet',
760 - 'n8n',
761 - 'salesforce',
762 - 'twilio',
763 - 'zapier',
764 - );
392 + $logging = array( 'api', 'salesforce', 'constantcontact', 'activecampaign' );
765 393 return in_array( $action_type, $logging, true ) && ! function_exists( 'frm_log_autoloader' );
766 394 }
767 395
768 - /**
769 - * @param int|string $form_id
770 - * @param array $values
771 - *
772 - * @return object
773 - */
774 396 private static function fields_to_values( $form_id, array &$values ) {
775 397 $form = FrmForm::getOne( $form_id );
776 398
777 399 $values = array(
@@ -779,14 +401,12 @@
779 401 'id' => $form->id,
780 402 );
781 403
782 404 $fields = FrmField::get_all_for_form( $form->id );
783 -
784 405 foreach ( $fields as $k => $f ) {
785 406 $f = (array) $f;
786 407 $opts = (array) $f['field_options'];
787 408 $f = array_merge( $opts, $f );
788 -
789 409 if ( ! isset( $f['post_field'] ) ) {
790 410 $f['post_field'] = '';
791 411 }
792 412 $values['fields'][] = $f;
@@ -797,15 +417,13 @@
797 417 }
798 418
799 419 /**
800 420 * @param int $form_id
801 - *
802 421 * @return void
803 422 */
804 423 public static function update_settings( $form_id ) {
805 424 FrmAppHelper::permission_check( 'frm_edit_forms' );
806 425 $process_form = FrmAppHelper::get_post_param( 'process_form', '', 'sanitize_text_field' );
807 -
808 426 if ( ! wp_verify_nonce( $process_form, 'process_form_nonce' ) ) {
809 427 $frm_settings = FrmAppHelper::get_settings();
810 428 $error_args = array(
811 429 'title' => __( 'Verification failed', 'formidable' ),
@@ -838,19 +456,17 @@
838 456 $new_actions = array();
839 457
840 458 foreach ( $registered_actions as $registered_action ) {
841 459 $action_ids = $registered_action->update_callback( $form_id );
842 -
843 - if ( $action_ids ) {
460 + if ( ! empty( $action_ids ) ) {
844 461 $new_actions[] = $action_ids;
845 462 }
846 463 }
847 464
848 465 // Only use array_merge if there are new actions.
849 - if ( $new_actions ) {
466 + if ( ! empty( $new_actions ) ) {
850 467 $new_actions = call_user_func_array( 'array_merge', $new_actions );
851 468 }
852 -
853 469 $old_actions = array_diff( $old_actions, $new_actions );
854 470
855 471 self::delete_missing_actions( $old_actions );
856 472
@@ -856,32 +472,17 @@
856 472
857 473 FrmOnSubmitHelper::save_on_submit_settings( $form_id );
858 474 }
859 475
860 - /**
861 - * @param array $old_actions
862 - *
863 - * @return void
864 - */
865 476 public static function delete_missing_actions( $old_actions ) {
866 - if ( ! $old_actions ) {
867 - return;
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' );
868 482 }
869 -
870 - foreach ( $old_actions as $old_id ) {
871 - wp_delete_post( $old_id );
872 - }
873 -
874 - FrmDb::cache_delete_group( 'frm_actions' );
875 483 }
876 484
877 - /**
878 - * @param int|string $entry_id
879 - * @param int|string $form_id
880 - * @param array $args
881 - *
882 - * @return void
883 - */
884 485 public static function trigger_create_actions( $entry_id, $form_id, $args = array() ) {
885 486 $filter_args = $args;
886 487 $filter_args['entry_id'] = $entry_id;
887 488 $filter_args['form_id'] = $form_id;
@@ -898,34 +499,23 @@
898 499 self::trigger_actions( $event, $form_id, $entry_id, 'all', $args );
899 500 }
900 501
901 502 /**
902 - * @param string $event
903 - * @param int|object|string $form
904 - * @param int|object|string $entry
905 - * @param string $type
906 - * @param array $args
907 - *
908 - * @return void
503 + * @param string $event
909 504 */
910 - public static function trigger_actions( $event, $form, $entry, $type = 'all', $args = array() ) { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh
505 + public static function trigger_actions( $event, $form, $entry, $type = 'all', $args = array() ) {
911 506 $action_status = array(
912 507 'post_status' => 'publish',
913 508 );
914 - $form_actions = FrmFormAction::get_action_for_form( is_object( $form ) ? $form->id : $form, $type, $action_status );
509 + $form_actions = FrmFormAction::get_action_for_form( ( is_object( $form ) ? $form->id : $form ), $type, $action_status );
915 510
916 - if ( ! $form_actions ) {
511 + if ( empty( $form_actions ) ) {
917 512 return;
918 513 }
919 514
920 515 FrmForm::maybe_get_form( $form );
921 516
922 - if ( ! is_object( $form ) ) {
923 - return;
924 - }
925 -
926 517 $link_settings = self::get_form_actions( $type );
927 -
928 518 if ( 'all' !== $type ) {
929 519 $link_settings = array( $type => $link_settings );
930 520 }
931 521
@@ -938,11 +528,11 @@
938 528 $this_event = $event;
939 529 }
940 530
941 531 foreach ( $form_actions as $action ) {
532 +
942 533 $skip_this_action = ! in_array( $this_event, $action->post_content['event'], true ) || FrmOnSubmitAction::$slug === $action->post_excerpt;
943 534 $skip_this_action = apply_filters( 'frm_skip_form_action', $skip_this_action, compact( 'action', 'entry', 'form', 'event' ) );
944 -
945 535 if ( $skip_this_action ) {
946 536 continue;
947 537 }
948 538
@@ -949,18 +539,17 @@
949 539 if ( ! is_object( $entry ) ) {
950 540 $entry = FrmEntry::getOne( $entry, true );
951 541 }
952 542
953 - if ( ! $entry || ( FrmEntriesHelper::DRAFT_ENTRY_STATUS === (int) $entry->is_draft && 'draft' !== $event ) ) {
543 + if ( empty( $entry ) || ( FrmEntriesHelper::DRAFT_ENTRY_STATUS === (int) $entry->is_draft && 'draft' !== $event ) ) {
954 544 continue;
955 545 }
956 546
957 - $child_entry = ( is_numeric( $form->parent_form_id ) && $form->parent_form_id ) || ( $entry && ( (int) $entry->form_id !== (int) $form->id || $entry->parent_item_id ) ) || ! empty( $args['is_child'] ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
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'] ) );
958 548
959 549 if ( $child_entry ) {
960 - // Maybe trigger actions for sub forms
550 + // maybe trigger actions for sub forms
961 551 $trigger_children = apply_filters( 'frm_use_embedded_form_actions', false, compact( 'form', 'entry' ) );
962 -
963 552 if ( ! $trigger_children ) {
964 553 continue;
965 554 }
966 555 }
@@ -966,9 +555,8 @@
966 555 }
967 556
968 557 // Check conditional logic.
969 558 $stop = FrmFormAction::action_conditions_met( $action, $entry );
970 -
971 559 if ( $stop ) {
972 560 continue;
973 561 }
974 562
@@ -978,9 +566,9 @@
978 566
979 567 unset( $action );
980 568 }//end foreach
981 569
982 - if ( $stored_actions ) {
570 + if ( ! empty( $stored_actions ) ) {
983 571 asort( $action_priority );
984 572
985 573 // Make sure hooks are loaded.
986 574 new FrmNotification();
@@ -1011,15 +599,8 @@
1011 599 }//end foreach
1012 600 }//end if
1013 601 }
1014 602
1015 - /**
1016 - * @param int|string $form_id
1017 - * @param array $values
1018 - * @param array $args
1019 - *
1020 - * @return void
1021 - */
1022 603 public static function duplicate_form_actions( $form_id, $values, $args = array() ) {
1023 604 if ( empty( $args['old_id'] ) ) {
1024 605 // Continue if we know which actions to copy.
1025 606 return;
@@ -1035,13 +616,8 @@
1035 616 unset( $action_control );
1036 617 }
1037 618 }
1038 619
1039 - /**
1040 - * @param string $where
1041 - *
1042 - * @return string
1043 - */
1044 620 public static function limit_by_type( $where ) {
1045 621 global $frm_vars, $wpdb;
1046 622
1047 623 if ( ! isset( $frm_vars['action_type'] ) ) {
@@ -1047,146 +623,15 @@
1047 623 if ( ! isset( $frm_vars['action_type'] ) ) {
1048 624 return $where;
1049 625 }
1050 626
1051 - return $where . $wpdb->prepare( ' AND post_excerpt = %s ', $frm_vars['action_type'] );
1052 - }
627 + $where .= $wpdb->prepare( ' AND post_excerpt = %s ', $frm_vars['action_type'] );
1053 628
1054 - /**
1055 - * Prevent WPML from filtering form actions based on the active language.
1056 - *
1057 - * @since 6.20
1058 - *
1059 - * @param bool|null $null
1060 - * @param string $post_type
1061 - *
1062 - * @return bool|null
1063 - */
1064 - public static function prevent_wpml_translations( $null, $post_type ) {
1065 - return self::$action_post_type === $post_type ? false : $null;
629 + return $where;
1066 630 }
1067 -
1068 - /**
1069 - * If Pro is not connected, hook a filter that will force all non-Lite
1070 - * actions to inactive so the upgrade popup is shown instead.
1071 - *
1072 - * @since 6.31
1073 - *
1074 - * @return void
1075 - */
1076 - private static function maybe_setup_unlicensed_action_gate() {
1077 - if ( FrmAppHelper::pro_is_connected() ) {
1078 - return;
1079 - }
1080 -
1081 - add_filter( 'frm_registered_form_actions', array( self::class, 'disable_unlicensed_actions' ), 100 );
1082 - }
1083 -
1084 - /**
1085 - * For every registered action that is not a Lite action, add a per-action
1086 - * options filter that forces it to inactive with the upgrade class.
1087 - *
1088 - * Runs inside apply_filters('frm_registered_form_actions') at priority 100,
1089 - * so the per-key option filters are in place before the class constructors
1090 - * run in the foreach loop that follows.
1091 - *
1092 - * @since 6.31
1093 - *
1094 - * @param array $actions Map of action_key => class_name.
1095 - *
1096 - * @return array
1097 - */
1098 - public static function disable_unlicensed_actions( $actions ) {
1099 - $lite_actions = array_fill_keys( self::get_lite_actions(), true );
1100 -
1101 - foreach ( array_keys( $actions ) as $key ) {
1102 - if ( isset( $lite_actions[ $key ] ) ) {
1103 - continue;
1104 - }
1105 -
1106 - add_filter(
1107 - 'frm_' . $key . '_action_options',
1108 - function ( $options ) {
1109 - $options['active'] = false;
1110 -
1111 - if ( ! str_contains( $options['classes'], 'frm_show_upgrade' ) ) {
1112 - $options['classes'] .= ' frm_show_upgrade';
1113 - }
1114 -
1115 - return $options;
1116 - }
1117 - );
1118 - }//end foreach
1119 -
1120 - return $actions;
1121 - }
1122 -
1123 - /**
1124 - * Get action keys that are available in Lite without a Pro license.
1125 - *
1126 - * @since 6.31
1127 - *
1128 - * @return string[]
1129 - */
1130 - public static function get_lite_actions() {
1131 - return apply_filters( 'frm_lite_form_actions', array( 'on_submit', 'email', 'payment', 'stripe', 'square', 'paypal', 'gated_content' ) );
1132 - }
1133 -
1134 - /**
1135 - * Single source of truth for learn-more URL slugs used in
1136 - * upgrade modals for non-Lite form actions.
1137 - *
1138 - * Slugs without '/' are KB doc slugs (knowledgebase/ prefix is added).
1139 - * Slugs with '/' are direct paths (e.g. features/) used as-is.
1140 - *
1141 - * @since 6.31
1142 - *
1143 - * @return array<string,string> Map of action_key => URL slug.
1144 - */
1145 - public static function get_action_learn_more_links() {
1146 - return array(
1147 - 'wppost' => 'features/user-submitted-posts-wordpress-forms',
1148 - 'register' => 'user-registration',
1149 - 'paypal' => 'features/paypal-wordpress-payments',
1150 - 'quiz' => 'quiz-maker-forms',
1151 - 'quiz_outcome' => 'quiz-maker-forms',
1152 - 'aweber' => 'features/aweber-addon',
1153 - 'mailchimp' => 'features/mailchimp-addon',
1154 - 'zapier' => 'features/form-entry-routing-with-zapier',
1155 - 'twilio' => 'features/twilio-sms-form-notifications',
1156 - 'activecampaign' => 'features/entries-to-activecampaign',
1157 - 'salesforce' => 'features/form-entries-to-salesforce',
1158 - 'constantcontact' => 'features/entries-to-constant-contact',
1159 - 'getresponse' => 'features/form-entries-to-getresponse',
1160 - 'hubspot' => 'features/form-entries-to-hubspot',
1161 - 'mailpoet' => 'features/mailpoet-newsletters-addon',
1162 - 'api' => 'features/wordpress-form-api',
1163 - 'googlespreadsheet' => 'features/google-sheets',
1164 - 'n8n' => 'features/connect-your-forms-to-any-app-with-n8n',
1165 - 'convertkit' => 'features/convertkit',
1166 - );
1167 - }
1168 -
1169 - /**
1170 - * Look up the learn-more doc slug for a given action key.
1171 - *
1172 - * @since 6.31
1173 - *
1174 - * @param string $action_key Action identifier (e.g. 'register').
1175 - *
1176 - * @return string Doc slug or empty string.
1177 - */
1178 - private static function get_learn_more_slug( $action_key ) {
1179 - $links = self::get_action_learn_more_links();
1180 - return $links[ $action_key ] ?? '';
1181 - }
1182 631 }
1183 632
1184 633 class Frm_Form_Action_Factory {
1185 -
1186 - /**
1187 - * @var array
1188 - */
1189 634 public $actions = array();
1190 635
1191 636 public function __construct() {
1192 637 add_action( 'frm_form_actions_init', array( $this, '_register_actions' ), 100 );
@@ -1191,22 +636,12 @@
1191 636 public function __construct() {
1192 637 add_action( 'frm_form_actions_init', array( $this, '_register_actions' ), 100 );
1193 638 }
1194 639
1195 - /**
1196 - * @param string $action_class
1197 - *
1198 - * @return void
1199 - */
1200 640 public function register( $action_class ) {
1201 641 $this->actions[ $action_class ] = new $action_class();
1202 642 }
1203 643
1204 - /**
1205 - * @param string $action_class
1206 - *
1207 - * @return void
1208 - */
1209 644 public function unregister( $action_class ) {
1210 645 if ( isset( $this->actions[ $action_class ] ) ) {
1211 646 unset( $this->actions[ $action_class ] );
1212 647 }
@@ -1215,9 +650,9 @@
1215 650 public function _register_actions() {
1216 651 $keys = array_keys( $this->actions );
1217 652
1218 653 foreach ( $keys as $key ) {
1219 - // Don't register new action if old action with the same id is already registered
654 + // don't register new action if old action with the same id is already registered
1220 655 if ( ! isset( $this->actions[ $key ] ) ) {
1221 656 $this->actions[ $key ]->_register();
1222 657 }
1223 658 }