PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.19
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.19
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 / stripe / controllers / FrmStrpLiteActionsController.php

FrmStrpLiteActionsController.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.19, at stripe/controllers/FrmStrpLiteActionsController.php

594 lines 17.1 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 FrmStrpLiteActionsController extends FrmTransLiteActionsController {
7
8 /**
9 * @var object|string|null A memoized value for the current Stripe customer object.
10 */
11 private static $customer;
12
13 /**
14 * Override the credit card field HTML if there is a Stripe action.
15 *
16 * @since 6.5, introduced in v2.0 of the Stripe add on.
17 *
18 * @param array $field
19 * @param string $field_name
20 * @param array $atts
21 * @return void
22 */
23 public static function show_card( $field, $field_name, $atts ) {
24 $actions = self::get_actions_before_submit( $field['form_id'] );
25
26 // Use the Pro function when there are no Stripe actions.
27 // This is required for other gateways like Authorize.Net.
28 if ( ! $actions && is_callable( 'FrmProCreditCardsController::show_in_form' ) ) {
29 FrmProCreditCardsController::show_in_form( $field, $field_name, $atts );
30 }
31
32 $html_id = $atts['html_id'];
33 include FrmStrpLiteAppHelper::plugin_path() . '/views/payments/card-field.php';
34 }
35
36 /**
37 * Get all published payment actions with the Stripe gateway that have an amount set.
38 *
39 * @since 6.5, introduced in v2.0 of the Stripe add on.
40 *
41 * @param int|string $form_id
42 * @return array
43 */
44 public static function get_actions_before_submit( $form_id ) {
45 $payment_actions = self::get_actions_for_form( $form_id );
46 foreach ( $payment_actions as $k => $payment_action ) {
47 $gateway = $payment_action->post_content['gateway'];
48 $is_stripe = $gateway === 'stripe' || ( is_array( $gateway ) && in_array( 'stripe', $gateway, true ) );
49 if ( ! $is_stripe || empty( $payment_action->post_content['amount'] ) ) {
50 unset( $payment_actions[ $k ] );
51 }
52 }
53 return $payment_actions;
54 }
55
56 /**
57 * Check the Stripe link action for a form. There should only be one.
58 * We want to ignore $action->post_content['stripe_link'].
59 * This way any Stripe action will fall back to Stripe link when the Stripe add on is unavailable.
60 *
61 * @since 6.5, introduced in v3.0 of the Stripe add on.
62 *
63 * @param int|string $form_id
64 * @return false|WP_Post
65 */
66 public static function get_stripe_link_action( $form_id ) {
67 $actions = self::get_actions_before_submit( $form_id );
68 return reset( $actions );
69 }
70
71 /**
72 * Trigger a Stripe payment after a form is submitted.
73 * This is called for both one time and recurring payments.
74 * It is also called when Stripe link is active but the Stripe payment is triggered instead with JavaScript.
75 *
76 * @param WP_Post $action
77 * @param stdClass $entry
78 * @param stdClass $form
79 * @return array
80 */
81 public static function trigger_gateway( $action, $entry, $form ) {
82 $response = array(
83 'success' => false,
84 'run_triggers' => false,
85 'show_errors' => true,
86 );
87 $atts = compact( 'action', 'entry', 'form' );
88
89 $amount = self::prepare_amount( $action->post_content['amount'], $atts );
90 if ( empty( $amount ) || $amount == 000 ) {
91 $response['error'] = __( 'Please specify an amount for the payment', 'formidable' );
92 return $response;
93 }
94
95 if ( ! self::stripe_is_configured() ) {
96 $response['error'] = __( 'There was a problem communicating with Stripe. Please try again.', 'formidable' );
97 return $response;
98 }
99
100 $customer = self::set_customer_with_token( $atts );
101 if ( ! is_object( $customer ) ) {
102 $response['error'] = $customer;
103 return $response;
104 }
105
106 $one_time_payment_args = compact( 'customer', 'form', 'entry', 'action', 'amount' );
107
108 FrmStrpLiteLinkController::create_pending_stripe_link_payment( $one_time_payment_args );
109 $response['show_errors'] = false;
110 return $response;
111 }
112
113 /**
114 * Check if either Stripe integration is enabled.
115 *
116 * @return bool true if Stripe Connect is set up.
117 */
118 private static function stripe_is_configured() {
119 return FrmStrpLiteAppHelper::call_stripe_helper_class( 'initialize_api' );
120 }
121
122 /**
123 * Set a customer object to $_POST['customer'] to use later.
124 *
125 * @param array $atts
126 * @return object|string
127 */
128 private static function set_customer_with_token( $atts ) {
129 if ( isset( self::$customer ) ) {
130 // It's an object if this isn't the first Stripe action running.
131 return self::$customer;
132 }
133
134 $payment_info = array(
135 'user_id' => FrmTransLiteAppHelper::get_user_id_for_current_payment(),
136 );
137
138 if ( ! empty( $atts['action']->post_content['email'] ) ) {
139 $payment_info['email'] = apply_filters( 'frm_content', $atts['action']->post_content['email'], $atts['form'], $atts['entry'] );
140 $payment_info['email'] = self::replace_email_shortcode( $payment_info['email'] );
141 }
142
143 self::add_customer_name( $atts, $payment_info );
144
145 $customer = FrmStrpLiteAppHelper::call_stripe_helper_class( 'get_customer', $payment_info );
146 // Set for later use.
147 self::$customer = $customer;
148
149 return $customer;
150 }
151
152 /**
153 * Replace an [email] shortcode with the current user email.
154 *
155 * @param string $email
156 * @return string
157 */
158 private static function replace_email_shortcode( $email ) {
159 if ( false === strpos( $email, '[email]' ) ) {
160 return $email;
161 }
162
163 global $current_user;
164 return str_replace(
165 '[email]',
166 ! empty( $current_user->user_email ) ? $current_user->user_email : '',
167 $email
168 );
169 }
170
171 /**
172 * Set the customer name based on the mapped first and last name fields in the Stripe action.
173 *
174 * @since 6.5, introduced in v2.02 of the Stripe add on.
175 *
176 * @param array $atts
177 * @param array $payment_info
178 * @return void
179 */
180 private static function add_customer_name( $atts, &$payment_info ) {
181 if ( empty( $atts['action']->post_content['billing_first_name'] ) ) {
182 return;
183 }
184
185 $name = '[' . $atts['action']->post_content['billing_first_name'] . ' show="first"]';
186 if ( ! empty( $atts['action']->post_content['billing_last_name'] ) ) {
187 $name .= ' [' . $atts['action']->post_content['billing_last_name'] . ' show="last"]';
188 }
189
190 $payment_info['name'] = apply_filters( 'frm_content', $name, $atts['form'], $atts['entry'] );
191 }
192
193 /**
194 * Get the trial period from the settings or from the connected entry.
195 *
196 * @since 6.5, introduced in v1.16 of the Stripe add on.
197 *
198 * @param array $atts Includes 'customer', 'entry', 'action', 'amount'.
199 * @return int The timestamp when the trial should end. 0 for no trial
200 */
201 public static function get_trial_end_time( $atts ) {
202 $settings = $atts['action']->post_content;
203 if ( empty( $settings['trial_interval_count'] ) ) {
204 return 0;
205 }
206
207 $trial = $settings['trial_interval_count'];
208 if ( ! is_numeric( $trial ) ) {
209 $trial = FrmTransLiteAppHelper::process_shortcodes(
210 array(
211 'value' => $trial,
212 'entry' => $atts['entry'],
213 )
214 );
215 }
216
217 if ( ! $trial ) {
218 return 0;
219 }
220
221 return strtotime( '+' . absint( $trial ) . ' days' );
222 }
223
224 /**
225 * Convert the amount from 10.00 to 1000.
226 *
227 * @param mixed $amount
228 * @param array $atts
229 * @return string
230 */
231 public static function prepare_amount( $amount, $atts = array() ) {
232 $amount = parent::prepare_amount( $amount, $atts );
233 $currency = self::get_currency_for_action( $atts );
234 return number_format( $amount, $currency['decimals'], '', '' );
235 }
236
237 /**
238 * Add defaults for additional Stripe action options.
239 *
240 * @param array $defaults
241 * @return array
242 */
243 public static function add_action_defaults( $defaults ) {
244 $defaults['plan_id'] = '';
245 $defaults['capture'] = '';
246 $defaults['stripe_link'] = '';
247 return $defaults;
248 }
249
250 /**
251 * Print additional options for Stripe action settings.
252 *
253 * @param array $atts
254 * @return void
255 */
256 public static function add_action_options( $atts ) {
257 $form_action = $atts['form_action'];
258 $action_control = $atts['action_control'];
259 include FrmStrpLiteAppHelper::plugin_path() . '/views/action-settings/options.php';
260 }
261
262 /**
263 * Filter Stripe action on save.
264 *
265 * @param array $settings
266 * @param array $action
267 * @return array
268 */
269 public static function before_save_settings( $settings, $action ) {
270 $settings['currency'] = strtolower( $settings['currency'] );
271
272 // In Lite Stripe link is always used.
273 $settings['stripe_link'] = 1;
274 $settings = self::create_plans( $settings );
275 $form_id = absint( $action['menu_order'] );
276
277 if ( empty( $settings['credit_card'] ) ) {
278 $credit_card_field_id = FrmDb::get_var(
279 'frm_fields',
280 array(
281 'type' => 'credit_card',
282 'form_id' => $form_id,
283 )
284 );
285 if ( ! $credit_card_field_id ) {
286 $credit_card_field_id = self::add_a_credit_card_field( $form_id );
287 }
288 if ( $credit_card_field_id ) {
289 $settings['credit_card'] = $credit_card_field_id;
290 }
291 }
292
293 $gateway_field_id = FrmDb::get_var(
294 'frm_fields',
295 array(
296 'type' => 'gateway',
297 'form_id' => $form_id,
298 )
299 );
300 if ( ! $gateway_field_id ) {
301 self::add_a_gateway_field( $form_id );
302 }
303
304 return $settings;
305 }
306
307 /**
308 * @param int $form_id
309 * @param string $field_type
310 * @param string $field_name
311 * @return false|int
312 */
313 private static function add_a_field( $form_id, $field_type, $field_name ) {
314 $new_values = FrmFieldsHelper::setup_new_vars( $field_type, $form_id );
315 $new_values['name'] = $field_name;
316 $field_id = FrmField::create( $new_values );
317 return $field_id;
318 }
319
320 /**
321 * A credit card field is added automatically if missing before a Stripe action is updated.
322 *
323 * @param int $form_id
324 * @return false|int
325 */
326 private static function add_a_credit_card_field( $form_id ) {
327 return self::add_a_field( $form_id, 'credit_card', __( 'Payment', 'formidable' ) );
328 }
329
330 /**
331 * A gateway field is added automatically for compatibility with the Stripe add on.
332 * The gateway field is not important for the Stripe Lite implementation.
333 *
334 * @param int $form_id
335 * @return false|int
336 */
337 private static function add_a_gateway_field( $form_id ) {
338 return self::add_a_field( $form_id, 'gateway', __( 'Payment Method', 'formidable' ) );
339 }
340
341 /**
342 * Create any required Stripe plans, used for subscriptions.
343 *
344 * @param array $settings
345 * @return array
346 */
347 public static function create_plans( $settings ) {
348 if ( $settings['type'] !== 'recurring' || strpos( $settings['amount'], ']' ) ) {
349 // Don't create a plan for one time payments, or for actions with shortcodes in the value.
350 $settings['plan_id'] = '';
351 return $settings;
352 }
353
354 $plan_opts = FrmStrpLiteSubscriptionHelper::prepare_plan_options( $settings );
355 if ( $plan_opts['id'] != $settings['plan_id'] ) {
356 $settings['plan_id'] = FrmStrpLiteSubscriptionHelper::maybe_create_plan( $plan_opts );
357 }
358
359 return $settings;
360 }
361
362 /**
363 * Include settings in the plan description in order to make sure the correct plan is used.
364 *
365 * @param array $settings
366 * @return string
367 */
368 public static function create_plan_id( $settings ) {
369 $amount = self::prepare_amount( $settings['amount'], $settings );
370 $id = sanitize_title_with_dashes( $settings['description'] ) . '_' . $amount . '_' . $settings['interval_count'] . $settings['interval'] . '_' . $settings['currency'];
371 return $id;
372 }
373
374 /**
375 * If this form submits with ajax, load the scripts on the first page.
376 *
377 * @param array $params
378 * @return void
379 */
380 public static function maybe_load_scripts( $params ) {
381 if ( $params['form_id'] == $params['posted_form_id'] ) {
382 // This form has already been posted, so we aren't on the first page.
383 return;
384 }
385
386 $form = FrmForm::getOne( $params['form_id'] );
387 if ( ! $form ) {
388 return;
389 }
390
391 $credit_card_field = FrmField::getAll(
392 array(
393 'fi.form_id' => $form->id,
394 'type' => 'credit_card',
395 )
396 );
397 if ( ! $credit_card_field ) {
398 return;
399 }
400
401 self::load_scripts( (int) $form->id );
402 }
403
404 /**
405 * Load front end JavaScript for a Stripe form.
406 *
407 * @param int $form_id
408 * @return void
409 */
410 public static function load_scripts( $form_id ) {
411 if ( FrmAppHelper::is_admin_page( 'formidable-entries' ) ) {
412 return;
413 }
414
415 if ( wp_script_is( 'formidable-stripe', 'enqueued' ) ) {
416 return;
417 }
418
419 $stripe_connect_is_setup = FrmStrpLiteConnectHelper::stripe_connect_is_setup();
420 if ( ! $stripe_connect_is_setup ) {
421 return;
422 }
423
424 if ( ! $form_id || ! is_int( $form_id ) ) {
425 _doing_it_wrong( __METHOD__, '$form_id parameter must be a non-zero integer', '6.5' );
426 return;
427 }
428
429 $settings = FrmStrpLiteAppHelper::get_settings();
430 $publishable = $settings->get_active_publishable_key();
431
432 wp_register_script(
433 'stripe',
434 'https://js.stripe.com/v3/',
435 array(),
436 '3.0',
437 false
438 );
439
440 $suffix = FrmAppHelper::js_suffix();
441 $dependencies = array( 'stripe', 'formidable' );
442
443 if ( '.min' === $suffix && is_readable( FrmAppHelper::plugin_path() . '/js/frmstrp.min.js' ) ) {
444 // Use the combined file if it is available.
445 $script_url = FrmAppHelper::plugin_url() . '/js/frmstrp.min.js';
446 } else {
447 if ( ! $suffix && ! is_readable( FrmStrpLiteAppHelper::plugin_path() . 'js/frmstrp.js' ) ) {
448 // The unminified file is not included in releases so force the minified script.
449 $suffix = '.min';
450 }
451 $script_url = FrmStrpLiteAppHelper::plugin_url() . 'js/frmstrp' . $suffix . '.js';
452 }
453
454 if ( class_exists( 'FrmProStrpLiteController' ) && ( ! $suffix || ! FrmProAppController::has_combo_js_file() ) ) {
455 $dependencies[] = 'formidablepro';
456 }
457
458 wp_enqueue_script(
459 'formidable-stripe',
460 $script_url,
461 $dependencies,
462 FrmAppHelper::plugin_version(),
463 false
464 );
465
466 $action_settings = self::prepare_settings_for_js( $form_id );
467 $style_settings = self::get_style_settings_for_form( $form_id );
468 $stripe_vars = array(
469 'publishable_key' => $publishable,
470 'form_id' => $form_id,
471 'nonce' => wp_create_nonce( 'frm_strp_ajax' ),
472 'ajax' => esc_url_raw( FrmAppHelper::get_ajax_url() ),
473 'settings' => $action_settings,
474 'locale' => self::get_locale(),
475 'baseFontSize' => $style_settings['field_font_size'],
476 'appearanceRules' => self::get_appearance_rules( $style_settings ),
477 'account_id' => FrmStrpLiteConnectHelper::get_account_id(),
478 );
479
480 wp_localize_script( 'formidable-stripe', 'frm_stripe_vars', $stripe_vars );
481 }
482
483 /**
484 * Get and format the style settings for JavaScript to use with the get_appearance_rules function.
485 *
486 * @since 6.5, introduced in v3.0 of the Stripe add on.
487 *
488 * @param mixed $form_id
489 * @return array
490 */
491 private static function get_style_settings_for_form( $form_id ) {
492 if ( ! $form_id ) {
493 return array();
494 }
495
496 $style = FrmStylesController::get_form_style( $form_id );
497 if ( ! $style ) {
498 return array();
499 }
500
501 $settings = FrmStylesHelper::get_settings_for_output( $style );
502 $disallowed = array( ';', ':', '!important' );
503 foreach ( $settings as $k => $s ) {
504 if ( is_string( $s ) ) {
505 $settings[ $k ] = str_replace( $disallowed, '', $s );
506 }
507 }
508
509 return $settings;
510 }
511
512 /**
513 * Get the style rules for Stripe link Authentication and Payment elements.
514 * These settings get set to frm_stripe_vars.appearanceRules.
515 * They're in the format that Stripe accepts.
516 * Documentation for Appearance rules can be found at https://stripe.com/docs/elements/appearance-api?platform=web#rules
517 *
518 * @since 6.5, introduced in v3.0 of the Stripe add on.
519 *
520 * @param array $settings
521 * @return array
522 */
523 private static function get_appearance_rules( $settings ) {
524 return array(
525 '.Input' => array(
526 'color' => $settings['text_color'],
527 'backgroundColor' => $settings['bg_color'],
528 'padding' => $settings['field_pad'],
529 'lineHeight' => 1.3,
530 'borderColor' => $settings['border_color'],
531 'borderWidth' => $settings['field_border_width'],
532 'borderStyle' => $settings['field_border_style'],
533 ),
534 '.Input::placeholder' => array(
535 'color' => $settings['text_color_disabled'],
536 ),
537 '.Input:focus' => array(
538 'backgroundColor' => $settings['bg_color_active'],
539 ),
540 '.Label' => array(
541 'color' => $settings['label_color'],
542 'fontSize' => $settings['font_size'],
543 'fontWeight' => $settings['weight'],
544 ),
545 '.Error' => array(
546 'color' => $settings['border_color_error'],
547 ),
548 );
549 }
550
551 /**
552 * Get the language to use for Stripe elements.
553 *
554 * @since 6.5, introduced in v2.0 of the Stripe add on.
555 * @return string
556 */
557 private static function get_locale() {
558 $allowed = array( 'ar', 'da', 'de', 'en', 'es', 'fi', 'fr', 'he', 'it', 'ja', 'nl', 'no', 'pl', 'ru', 'sv', 'zh' );
559 $current = get_locale();
560 $parts = explode( '_', $current );
561 $part = strtolower( $parts[0] );
562 return in_array( $part, $allowed, true ) ? $part : 'auto';
563 }
564
565 /**
566 * If the names are being used on the CC fields,
567 * make sure it doesn't prevent the submission if Stripe has approved.
568 *
569 * @since 6.7.1
570 *
571 * @param array $errors
572 * @param stdClass $field
573 * @param array $values
574 * @return array
575 */
576 public static function remove_cc_validation( $errors, $field, $values ) {
577 $has_processed = isset( $_POST[ 'frmintent' . $field->form_id ] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
578 if ( ! $has_processed ) {
579 return $errors;
580 }
581
582 $field_id = isset( $field->temp_id ) ? $field->temp_id : $field->id;
583
584 if ( isset( $errors[ 'field' . $field_id . '-cc' ] ) ) {
585 unset( $errors[ 'field' . $field_id . '-cc' ] );
586 }
587 if ( isset( $errors[ 'field' . $field_id ] ) ) {
588 unset( $errors[ 'field' . $field_id ] );
589 }
590
591 return $errors;
592 }
593 }
594