PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
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 | stripe/controllers/FrmTransLiteActionsController.php +362 -35 6.5 → trunk View file →
@@ -5,11 +5,20 @@
5 5
6 6 class FrmTransLiteActionsController {
7 7
8 8 /**
9 + * Track the entry IDs we're destroying so we don't attempt to delete an entry more than once.
10 + * Set in self::destroy_entry_later.
11 + *
12 + * @var array
13 + */
14 + private static $entry_ids_to_destroy_later = array();
15 +
16 + /**
9 17 * Register payment action type.
10 18 *
11 19 * @param array $actions
20 + *
12 21 * @return array
13 22 */
14 23 public static function register_actions( $actions ) {
15 24 $actions['payment'] = 'FrmTransLiteAction';
@@ -26,9 +35,9 @@
26 35 public static function actions_js() {
27 36 wp_enqueue_script(
28 37 'frmtrans_admin',
29 38 FrmTransLiteAppHelper::plugin_url() . '/js/frmtrans_admin.js',
30 - array( 'jquery' ),
39 + array( 'jquery', 'wp-hooks' ),
31 40 FrmAppHelper::plugin_version()
32 41 );
33 42 wp_localize_script(
34 43 'frmtrans_admin',
@@ -42,13 +51,15 @@
42 51 /**
43 52 * Add event types for actions so an email can trigger on a successful payment.
44 53 *
45 54 * @param array $triggers
55 + *
46 56 * @return array
47 57 */
48 58 public static function add_payment_trigger( $triggers ) {
49 59 $triggers['payment-success'] = __( 'Successful Payment', 'formidable' );
50 60 $triggers['payment-failed'] = __( 'Failed Payment', 'formidable' );
61 + $triggers['payment-refunded'] = __( 'Refunded Payment', 'formidable' );
51 62 $triggers['payment-processing'] = __( 'Processing Payment', 'formidable' );
52 63 $triggers['payment-future-cancel'] = __( 'Canceled Subscription', 'formidable' );
53 64 $triggers['payment-canceled'] = __( 'Subscription Canceled and Expired', 'formidable' );
54 65 return $triggers;
@@ -55,8 +66,9 @@
55 66 }
56 67
57 68 /**
58 69 * @param array $options
70 + *
59 71 * @return array
60 72 */
61 73 public static function add_trigger_to_action( $options ) {
62 74 $options['event'][] = 'payment-success';
@@ -63,8 +75,9 @@
63 75 $options['event'][] = 'payment-failed';
64 76 $options['event'][] = 'payment-processing';
65 77 $options['event'][] = 'payment-future-cancel';
66 78 $options['event'][] = 'payment-canceled';
79 + $options['event'][] = 'payment-refunded';
67 80 return $options;
68 81 }
69 82
70 83 /**
@@ -70,19 +83,95 @@
70 83 /**
71 84 * @param WP_Post $action
72 85 * @param stdClass $entry
73 86 * @param mixed $form
87 + *
74 88 * @return void
75 89 */
76 90 public static function trigger_action( $action, $entry, $form ) {
77 91 self::prepare_description( $action, compact( 'entry', 'form' ) );
78 - FrmStrpLiteActionsController::trigger_gateway( $action, $entry, $form );
92 +
93 + $gateway = self::get_gateway_for_action( $action );
94 +
95 + if ( ! $gateway ) {
96 + return;
97 + }
98 +
99 + $class_name = FrmTransLiteAppHelper::get_setting_for_gateway( $gateway, 'class' );
100 +
101 + if ( ! $class_name ) {
102 + return;
103 + }
104 +
105 + $class_name = 'Frm' . $class_name . 'ActionsController';
106 + $response = $class_name::trigger_gateway( $action, $entry, $form );
107 +
108 + if ( ! $response['success'] && $response['show_errors'] ) {
109 + // The payment failed
110 + self::show_failed_message( compact( 'action', 'entry', 'form', 'response' ) );
111 + }
79 112 }
80 113
81 114 /**
115 + * @param WP_Post $action
116 + *
117 + * @return array|string
118 + */
119 + private static function get_gateway_for_action( $action ) {
120 + return $action->post_content['gateway'] ?? 'stripe';
121 + }
122 +
123 + /**
124 + * @since 6.10
125 + *
126 + * @param array $args
127 + *
128 + * @return void
129 + */
130 + private static function show_failed_message( $args ) {
131 + global $frm_vars;
132 + $frm_vars['frm_trans'] = array(
133 + 'pay_entry' => $args['entry'],
134 + 'error' => $args['response']['error'] ?? '',
135 + );
136 +
137 + add_filter( 'frm_success_filter', 'FrmTransLiteActionsController::force_message_after_create' );
138 + add_filter( 'frm_pre_display_form', 'FrmTransLiteActionsController::include_form_with_success' );
139 + add_filter( 'frm_main_feedback', 'FrmTransLiteActionsController::replace_success_message', 5 );
140 + add_filter( 'frm_setup_new_fields_vars', 'FrmTransLiteActionsController::fill_entry_from_previous', 20, 2 );
141 + }
142 +
143 + /**
144 + * @since 6.10
145 + *
146 + * @param stdClass $form
147 + *
148 + * @return stdClass
149 + */
150 + public static function include_form_with_success( $form ) {
151 + $form->options['show_form'] = 1;
152 + return $form;
153 + }
154 +
155 + /**
156 + * @return string
157 + */
158 + public static function replace_success_message() {
159 + global $frm_vars;
160 + $message = $frm_vars['frm_trans']['error'] ?? '';
161 +
162 + if ( ! $message ) {
163 + $message = __( 'There was an error processing your payment.', 'formidable' );
164 + }
165 +
166 + return '<div class="frm_error_style">' . $message . '</div>';
167 + }
168 +
169 + /**
82 170 * @param WP_Post $action
83 171 * @param stdClass $entry
84 172 * @param mixed $form
173 + *
85 174 * @return array
86 175 */
87 176 public static function trigger_gateway( $action, $entry, $form ) {
88 177 // This function must be overridden in a subclass.
@@ -103,8 +192,9 @@
103 192 /**
104 193 * @since 6.5, introduced in v1.12 of the Payments submodule.
105 194 *
106 195 * @param object $sub
196 + *
107 197 * @return void
108 198 */
109 199 public static function trigger_subscription_status_change( $sub ) {
110 200 $frm_payment = new FrmTransLitePayment();
@@ -121,14 +211,14 @@
121 211 }
122 212
123 213 /**
124 214 * @param array $atts
215 + *
125 216 * @return void
126 217 */
127 218 public static function trigger_payment_status_change( $atts ) {
128 - $action = isset( $atts['action'] ) ? $atts['action'] : $atts['payment']->action_id;
129 219 $entry_id = isset( $atts['entry'] ) ? $atts['entry']->id : $atts['payment']->item_id;
130 - $atts = array(
220 + $atts = array(
131 221 'trigger' => $atts['status'],
132 222 'entry_id' => $entry_id,
133 223 );
134 224
@@ -143,8 +233,17 @@
143 233
144 234 // Set future-cancel as trigger when applicable.
145 235 $atts['trigger'] = str_replace( '_', '-', $atts['trigger'] );
146 236
237 + /**
238 + * Trigger various hooks including frm_payment_status_complete.
239 + *
240 + * @since 6.25 This was included in the payments submodule, but not included in Lite until 6.25.
241 + *
242 + * @param array $atts
243 + */
244 + do_action( 'frm_payment_status_' . $atts['trigger'], $atts );
245 +
147 246 if ( $atts['payment'] ) {
148 247 self::trigger_actions_after_payment( $atts['payment'], $atts );
149 248 }
150 249 }
@@ -153,32 +252,25 @@
153 252 * Maybe trigger payment-success or payment-failed event after payment so actions (like emails) can run.
154 253 *
155 254 * @param object $payment
156 255 * @param array $atts
256 + *
157 257 * @return void
158 258 */
159 259 public static function trigger_actions_after_payment( $payment, $atts = array() ) {
160 - if ( ! is_callable( 'FrmFormActionsController::trigger_actions' ) ) {
161 - return;
162 - }
163 -
164 260 if ( 'pending' === $payment->status ) {
165 261 // 3D Secure has a delayed payment status, so avoid sending a payment failed email for a pending payment.
166 262 return;
167 263 }
168 264
169 - $entry = FrmEntry::getOne( $payment->item_id );
265 + $entry = FrmEntry::getOne( $payment->item_id );
266 + $trigger_event = isset( $atts['trigger'] ) ? 'payment-' . $atts['trigger'] : 'payment-' . $payment->status;
267 + $allowed_triggers = array_keys( self::add_payment_trigger( array() ) );
170 268
171 - if ( isset( $atts['trigger'] ) ) {
172 - $trigger_event = 'payment-' . $atts['trigger'];
173 - } else {
174 - $trigger_event = 'payment-' . $payment->status;
269 + if ( ! in_array( $trigger_event, $allowed_triggers, true ) ) {
270 + $trigger_event = $payment->status === 'complete' ? 'payment-success' : 'payment-failed';
175 271 }
176 272
177 - $allowed_triggers = array_keys( self::add_payment_trigger( array() ) );
178 - if ( ! in_array( $trigger_event, $allowed_triggers, true ) ) {
179 - $trigger_event = ( $payment->status === 'complete' ) ? 'payment-success' : 'payment-failed';
180 - }
181 273 FrmFormActionsController::trigger_actions( $trigger_event, $entry->form_id, $entry->id );
182 274 }
183 275
184 276 /**
@@ -185,17 +277,21 @@
185 277 * Filter fields in description.
186 278 *
187 279 * @param WP_Post $action
188 280 * @param array $atts
281 + *
189 282 * @return void
190 283 */
191 284 public static function prepare_description( &$action, $atts ) {
192 285 $description = $action->post_content['description'];
193 - if ( ! empty( $description ) ) {
194 - $atts['value'] = $description;
195 - $description = FrmTransLiteAppHelper::process_shortcodes( $atts );
196 - $action->post_content['description'] = $description;
286 +
287 + if ( ! $description ) {
288 + return;
197 289 }
290 +
291 + $atts['value'] = $description;
292 + $description = FrmTransLiteAppHelper::process_shortcodes( $atts );
293 + $action->post_content['description'] = $description;
198 294 }
199 295
200 296 /**
201 297 * Convert the amount into 10.00.
@@ -201,24 +297,25 @@
201 297 * Convert the amount into 10.00.
202 298 *
203 299 * @param mixed $amount
204 300 * @param array $atts
301 + *
205 302 * @return string
206 303 */
207 304 public static function prepare_amount( $amount, $atts = array() ) {
208 305 if ( isset( $atts['form'] ) ) {
209 306 $atts['value'] = $amount;
210 - $amount = FrmTransLiteAppHelper::process_shortcodes( $atts );
307 + $amount = FrmTransLiteAppHelper::process_shortcodes( $atts );
211 308 }
212 309
213 - if ( is_string( $amount ) && strlen( $amount ) >= 2 && $amount[0] == '[' && substr( $amount, -1 ) == ']' ) {
214 - // make sure we don't use a field id as the amount
310 + if ( is_string( $amount ) && strlen( $amount ) >= 2 && $amount[0] === '[' && str_ends_with( $amount, ']' ) ) {
311 + // Make sure we don't use a field id as the amount.
215 312 $amount = 0;
216 313 }
217 314
218 315 $currency = self::get_currency_for_action( $atts );
316 + $total = 0;
219 317
220 - $total = 0;
221 318 foreach ( (array) $amount as $a ) {
222 319 $this_amount = self::get_amount_from_string( $a );
223 320 self::maybe_use_decimal( $this_amount, $currency );
224 321 self::normalize_number( $this_amount, $currency );
@@ -233,12 +330,14 @@
233 330 /**
234 331 * Get currency to use when preparing amount.
235 332 *
236 333 * @param array $atts
334 + *
237 335 * @return array
238 336 */
239 337 public static function get_currency_for_action( $atts ) {
240 338 $currency = 'usd';
339 +
241 340 if ( isset( $atts['form'] ) ) {
242 341 $currency = $atts['action']->post_content['currency'];
243 342 } elseif ( isset( $atts['currency'] ) ) {
244 343 $currency = $atts['currency'];
@@ -255,15 +354,15 @@
255 354 private static function get_amount_from_string( $amount ) {
256 355 $amount = html_entity_decode( $amount );
257 356 $amount = trim( $amount );
258 357 preg_match_all( '/[0-9,.]*\.?\,?[0-9]+/', $amount, $matches );
259 - $amount = $matches ? end( $matches[0] ) : 0;
260 - return $amount;
358 + return $matches ? end( $matches[0] ) : 0;
261 359 }
262 360
263 361 /**
264 362 * @param string $amount
265 363 * @param array $currency
364 + *
266 365 * @return void
267 366 */
268 367 private static function maybe_use_decimal( &$amount, $currency ) {
269 368 if ( $currency['thousand_separator'] !== '.' ) {
@@ -269,10 +368,17 @@
269 368 if ( $currency['thousand_separator'] !== '.' ) {
270 369 return;
271 370 }
272 371
273 - $amount_parts = explode( '.', $amount );
274 - $used_for_decimal = count( $amount_parts ) === 2 && strlen( $amount_parts[1] ) === 2;
372 + $amount_parts = explode( '.', $amount );
373 +
374 + if ( 2 !== count( $amount_parts ) ) {
375 + return;
376 + }
377 +
378 + $strlen = strlen( $amount_parts[1] );
379 + $used_for_decimal = $strlen === 1 || $strlen === 2;
380 +
275 381 if ( $used_for_decimal ) {
276 382 $amount = str_replace( '.', $currency['decimal_separator'], $amount );
277 383 }
278 384 }
@@ -279,8 +385,9 @@
279 385
280 386 /**
281 387 * @param string $amount
282 388 * @param array $currency
389 + *
283 390 * @return void
284 391 */
285 392 private static function normalize_number( &$amount, $currency ) {
286 393 $amount = str_replace( $currency['thousand_separator'], '', $amount );
@@ -291,22 +398,26 @@
291 398 /**
292 399 * These settings are included in frm_stripe_vars.settings global JavaScript object on Stripe forms.
293 400 *
294 401 * @param int $form_id
402 + *
295 403 * @return array
296 404 */
297 405 public static function prepare_settings_for_js( $form_id ) {
298 406 $payment_actions = self::get_actions_for_form( $form_id );
299 407 $action_settings = array();
408 +
300 409 foreach ( $payment_actions as $payment_action ) {
301 410 $settings_for_action = array(
302 411 'id' => $payment_action->ID,
303 412 'first_name' => $payment_action->post_content['billing_first_name'],
304 413 'last_name' => $payment_action->post_content['billing_last_name'],
414 + 'address' => $payment_action->post_content['billing_address'] ?? '',
305 415 'gateways' => $payment_action->post_content['gateway'],
306 416 'fields' => self::get_fields_for_price( $payment_action ),
307 417 'one' => $payment_action->post_content['type'],
308 418 'email' => $payment_action->post_content['email'],
419 + 'layout' => $payment_action->post_content['layout'] ?? '',
309 420 );
310 421
311 422 /**
312 423 * @param array $settings_for_action
@@ -312,9 +423,9 @@
312 423 * @param array $settings_for_action
313 424 * @param WP_Post $payment_action
314 425 */
315 426 $settings_for_action = apply_filters( 'frm_trans_settings_for_js', $settings_for_action, $payment_action );
316 - $action_settings[] = $settings_for_action;
427 + $action_settings[] = $settings_for_action;
317 428 }
318 429
319 430 return $action_settings;
320 431 }
@@ -324,14 +435,15 @@
324 435 *
325 436 * @since 6.5, introduced in v2.0 of the Payments submodule.
326 437 *
327 438 * @param WP_Post $action
439 + *
328 440 * @return array|int
329 441 */
330 442 private static function get_fields_for_price( $action ) {
331 443 $amount = $action->post_content['amount'];
332 444 $shortcodes = FrmFieldsHelper::get_shortcodes( $amount, $action->menu_order );
333 - return isset( $shortcodes[2] ) ? $shortcodes[2] : -1;
445 + return $shortcodes[2] ?? -1;
334 446 }
335 447
336 448 /**
337 449 * Get all published payment actions.
@@ -336,8 +448,9 @@
336 448 /**
337 449 * Get all published payment actions.
338 450 *
339 451 * @param int|string $form_id
452 + *
340 453 * @return array
341 454 */
342 455 public static function get_actions_for_form( $form_id ) {
343 456 $action_status = array(
@@ -343,12 +456,10 @@
343 456 $action_status = array(
344 457 'post_status' => 'publish',
345 458 );
346 459 $payment_actions = FrmFormAction::get_action_for_form( $form_id, 'payment', $action_status );
347 - if ( ! $payment_actions ) {
348 - $payment_actions = array();
349 - }
350 - return $payment_actions;
460 +
461 + return $payment_actions ? $payment_actions : array();
351 462 }
352 463
353 464 /**
354 465 * Make sure a gateway field is hidden on the front end.
@@ -354,8 +465,9 @@
354 465 * Make sure a gateway field is hidden on the front end.
355 466 *
356 467 * @param array $values
357 468 * @param stdClass $field
469 + *
358 470 * @return array
359 471 */
360 472 public static function hide_gateway_field_on_front_end( $values, $field ) {
361 473 if ( $field->type !== 'gateway' ) {
@@ -361,13 +473,228 @@
361 473 if ( $field->type !== 'gateway' ) {
362 474 return $values;
363 475 }
364 476
477 + if ( FrmAppHelper::is_form_builder_page() ) {
478 + // The hooks this uses can get called in the form builder and settings pages.
479 + // But we do not need the script in this case.
480 + return $values;
481 + }
482 +
365 483 // This is also called from the frm_enqueue_form_scripts hook.
366 484 // With this here, the value of frm_stripe_vars.settings[0].fields is -1
367 485 // This is because the amount value is processed and a shortcode is not found in '000'.
368 486 FrmStrpLiteActionsController::load_scripts( (int) $field->form_id );
487 + FrmSquareLiteActionsController::load_scripts( (int) $field->form_id );
369 488
370 489 $values['type'] = 'hidden';
371 490 return $values;
491 + }
492 +
493 + /**
494 + * Entries are deleted on payment failure so set the form values after an error from the entry data that gets deleted.
495 + *
496 + * @since 6.5.1
497 + *
498 + * @param array $values
499 + * @param stdClass $field
500 + *
501 + * @return array
502 + */
503 + public static function fill_entry_from_previous( $values, $field ) {
504 + global $frm_vars;
505 + $previous_entry = $frm_vars['frm_trans']['pay_entry'] ?? false;
506 +
507 + // phpcs:ignore Universal.Operators.StrictComparisons
508 + if ( ! $previous_entry || $previous_entry->form_id != $field->form_id ) {
509 + return $values;
510 + }
511 +
512 + if ( is_array( $previous_entry->metas ) && isset( $previous_entry->metas[ $field->id ] ) ) {
513 + $values['value'] = $previous_entry->metas[ $field->id ];
514 + }
515 +
516 + $frm_vars['trans_filled'] = true;
517 + $previous_entry_id = $previous_entry->id;
518 + self::destroy_entry_later( $previous_entry_id );
519 +
520 + return $values;
521 + }
522 +
523 + /**
524 + * Destroy an entry, but delay it to happen when the form is displayed.
525 + * It needs to happen late enough that FrmProNestedFormsController::display_single_iteration_of_nested_form is able to fill in data for repeater fields.
526 + * See Formidable Stripe issue #136 for more information.
527 + *
528 + * @since 6.5.1
529 + *
530 + * @param int|string $entry_id
531 + *
532 + * @return void
533 + */
534 + private static function destroy_entry_later( $entry_id ) {
535 + if ( in_array( (int) $entry_id, self::$entry_ids_to_destroy_later, true ) ) {
536 + // Avoid trying to delete this multiple times as fill_entry_from_previous is called more than once.
537 + return;
538 + }
539 +
540 + $destroy_callback =
541 + /**
542 + * Destroy an entry and remove this action so it only tries to destroy the entry once.
543 + *
544 + * @param int|string $entry_id
545 + * @param Closure $destroy_callback
546 + *
547 + * @return void
548 + */
549 + function () use ( $entry_id, &$destroy_callback ) {
550 + FrmEntry::destroy( $entry_id );
551 + // Only call this once.
552 + remove_action( 'frm_entry_form', $destroy_callback );
553 + };
554 + add_action( 'frm_entry_form', $destroy_callback );
555 +
556 + self::$entry_ids_to_destroy_later[] = (int) $entry_id;
557 + }
558 +
559 + /**
560 + * Filter payment action on save.
561 + *
562 + * @since 6.22
563 + *
564 + * @param array $settings
565 + * @param array $action
566 + *
567 + * @return array
568 + */
569 + public static function before_save_settings( $settings, $action ) {
570 + $settings['gateway'] = ! empty( $settings['gateway'] ) ? (array) $settings['gateway'] : array( 'stripe' );
571 +
572 + if ( in_array( 'square', $settings['gateway'], true ) ) {
573 + $currency = FrmSquareLiteConnectHelper::get_merchant_currency();
574 + $settings['currency'] = false !== $currency ? strtolower( $currency ) : 'usd';
575 + } else {
576 + $settings['currency'] = strtolower( $settings['currency'] );
577 + }
578 +
579 + $form_id = absint( $action['menu_order'] );
580 +
581 + if ( empty( $settings['credit_card'] ) ) {
582 + $credit_card_field_id = FrmDb::get_var(
583 + 'frm_fields',
584 + array(
585 + 'type' => 'credit_card',
586 + 'form_id' => $form_id,
587 + )
588 + );
589 +
590 + if ( ! $credit_card_field_id ) {
591 + $credit_card_field_id = self::add_a_credit_card_field( $form_id );
592 + }
593 +
594 + if ( $credit_card_field_id ) {
595 + $settings['credit_card'] = $credit_card_field_id;
596 + }
597 + }
598 +
599 + if ( ! in_array( 'stripe', $settings['gateway'], true ) ) {
600 + // We only need a gateway field for Stripe add-on compatibility,
601 + // so unless Stripe is selected, we can return early.
602 + return $settings;
603 + }
604 +
605 + $gateway_field_id = FrmDb::get_var(
606 + 'frm_fields',
607 + array(
608 + 'type' => 'gateway',
609 + 'form_id' => $form_id,
610 + )
611 + );
612 +
613 + if ( ! $gateway_field_id ) {
614 + self::add_a_gateway_field( $form_id );
615 + }
616 +
617 + return $settings;
618 + }
619 +
620 + /**
621 + * A credit card field is added automatically if missing before a Stripe action is updated.
622 + *
623 + * @param int $form_id
624 + *
625 + * @return false|int
626 + */
627 + protected static function add_a_credit_card_field( $form_id ) {
628 + return self::add_a_field( $form_id, 'credit_card', __( 'Payment', 'formidable' ) );
629 + }
630 +
631 + /**
632 + * A gateway field is added automatically for compatibility with the Stripe add on.
633 + * The gateway field is not important for the Stripe Lite implementation.
634 + *
635 + * @param int $form_id
636 + *
637 + * @return false|int
638 + */
639 + protected static function add_a_gateway_field( $form_id ) {
640 + return self::add_a_field( $form_id, 'gateway', __( 'Payment Method', 'formidable' ) );
641 + }
642 +
643 + /**
644 + * @param int $form_id
645 + * @param string $field_type
646 + * @param string $field_name
647 + *
648 + * @return false|int
649 + */
650 + protected static function add_a_field( $form_id, $field_type, $field_name ) {
651 + $new_values = FrmFieldsHelper::setup_new_vars( $field_type, $form_id );
652 + $new_values['name'] = $field_name;
653 + $new_values['field_order'] = self::get_field_order_before_submit( $form_id, $new_values['field_order'] );
654 + return FrmField::create( $new_values );
655 + }
656 +
657 + /**
658 + * When auto-injecting a field, ensure it is placed before the submit button.
659 + *
660 + * @since 6.29
661 + *
662 + * @param int $form_id
663 + * @param int $field_order
664 + *
665 + * @return int
666 + */
667 + private static function get_field_order_before_submit( $form_id, $field_order ) {
668 + $submit_field = FrmSubmitHelper::get_submit_field( $form_id );
669 +
670 + if ( ! $submit_field || $field_order < (int) $submit_field->field_order ) {
671 + return $field_order;
672 + }
673 +
674 + $submit_order = (int) $submit_field->field_order;
675 + FrmField::update( $submit_field->id, array( 'field_order' => $submit_order + 1 ) );
676 + return $submit_order;
677 + }
678 +
679 + /**
680 + * Remove credit card validation errors.
681 + *
682 + * @param array $errors
683 + * @param stdClass $field
684 + *
685 + * @return array
686 + */
687 + public static function remove_cc_errors( $errors, $field ) {
688 + $field_id = $field->temp_id ?? $field->id;
689 +
690 + if ( isset( $errors[ 'field' . $field_id . '-cc' ] ) ) {
691 + unset( $errors[ 'field' . $field_id . '-cc' ] );
692 + }
693 +
694 + if ( isset( $errors[ 'field' . $field_id ] ) ) {
695 + unset( $errors[ 'field' . $field_id ] );
696 + }
697 +
698 + return $errors;
372 699 }
373 700 }