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

563 lines 16.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 class 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 string|int $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 string|int $form_id
64 * @return WP_Post|false
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 self::$customer = $customer; // Set for later use.
147
148 return $customer;
149 }
150
151 /**
152 * Replace an [email] shortcode with the current user email.
153 *
154 * @param string $email
155 * @return string
156 */
157 private static function replace_email_shortcode( $email ) {
158 if ( false === strpos( $email, '[email]' ) ) {
159 return $email;
160 }
161
162 global $current_user;
163 return str_replace(
164 '[email]',
165 ! empty( $current_user->user_email ) ? $current_user->user_email : '',
166 $email
167 );
168 }
169
170 /**
171 * Set the customer name based on the mapped first and last name fields in the Stripe action.
172 *
173 * @since 6.5, introduced in v2.02 of the Stripe add on.
174 *
175 * @param array $atts
176 * @param array $payment_info
177 * @return void
178 */
179 private static function add_customer_name( $atts, &$payment_info ) {
180 if ( empty( $atts['action']->post_content['billing_first_name'] ) ) {
181 return;
182 }
183
184 $name = '[' . $atts['action']->post_content['billing_first_name'] . ' show="first"]';
185 if ( ! empty( $atts['action']->post_content['billing_last_name'] ) ) {
186 $name .= ' [' . $atts['action']->post_content['billing_last_name'] . ' show="last"]';
187 }
188
189 $payment_info['name'] = apply_filters( 'frm_content', $name, $atts['form'], $atts['entry'] );
190 }
191
192 /**
193 * Get the trial period from the settings or from the connected entry.
194 *
195 * @since 6.5, introduced in v1.16 of the Stripe add on.
196 *
197 * @param array $atts Includes 'customer', 'entry', 'action', 'amount'.
198 * @return int The timestamp when the trial should end. 0 for no trial
199 */
200 public static function get_trial_end_time( $atts ) {
201 $settings = $atts['action']->post_content;
202 if ( empty( $settings['trial_interval_count'] ) ) {
203 return 0;
204 }
205
206 $trial = $settings['trial_interval_count'];
207 if ( ! is_numeric( $trial ) ) {
208 $trial = FrmTransLiteAppHelper::process_shortcodes(
209 array(
210 'value' => $trial,
211 'entry' => $atts['entry'],
212 )
213 );
214 }
215
216 if ( ! $trial ) {
217 return 0;
218 }
219
220 return strtotime( '+' . absint( $trial ) . ' days' );
221 }
222
223 /**
224 * Convert the amount from 10.00 to 1000.
225 *
226 * @param mixed $amount
227 * @param array $atts
228 * @return string
229 */
230 public static function prepare_amount( $amount, $atts = array() ) {
231 $amount = parent::prepare_amount( $amount, $atts );
232 $currency = self::get_currency_for_action( $atts );
233 return number_format( $amount, $currency['decimals'], '', '' );
234 }
235
236 /**
237 * Add defaults for additional Stripe action options.
238 *
239 * @param array $defaults
240 * @return array
241 */
242 public static function add_action_defaults( $defaults ) {
243 $defaults['plan_id'] = '';
244 $defaults['capture'] = '';
245 $defaults['stripe_link'] = '';
246 return $defaults;
247 }
248
249 /**
250 * Print additional options for Stripe action settings.
251 *
252 * @param array $atts
253 * @return void
254 */
255 public static function add_action_options( $atts ) {
256 $form_action = $atts['form_action'];
257 $action_control = $atts['action_control'];
258 include FrmStrpLiteAppHelper::plugin_path() . '/views/action-settings/options.php';
259 }
260
261 /**
262 * Filter Stripe action on save.
263 *
264 * @param array $settings
265 * @param array $action
266 * @return array
267 */
268 public static function before_save_settings( $settings, $action ) {
269 $settings['currency'] = strtolower( $settings['currency'] );
270 $settings['stripe_link'] = 1; // In Lite Stripe link is always used.
271 $settings = self::create_plans( $settings );
272 $form_id = absint( $action['menu_order'] );
273
274 if ( empty( $settings['credit_card'] ) ) {
275 $credit_card_field_id = FrmDb::get_var(
276 'frm_fields',
277 array(
278 'type' => 'credit_card',
279 'form_id' => $form_id,
280 )
281 );
282 if ( ! $credit_card_field_id ) {
283 $credit_card_field_id = self::add_a_credit_card_field( $form_id );
284 }
285 if ( $credit_card_field_id ) {
286 $settings['credit_card'] = $credit_card_field_id;
287 }
288 }
289
290 $gateway_field_id = FrmDb::get_var(
291 'frm_fields',
292 array(
293 'type' => 'gateway',
294 'form_id' => $form_id,
295 )
296 );
297 if ( ! $gateway_field_id ) {
298 self::add_a_gateway_field( $form_id );
299 }
300
301 return $settings;
302 }
303
304 /**
305 * @param int $form_id
306 * @param string $field_type
307 * @param string $field_name
308 * @return int|false
309 */
310 private static function add_a_field( $form_id, $field_type, $field_name ) {
311 $new_values = FrmFieldsHelper::setup_new_vars( $field_type, $form_id );
312 $new_values['name'] = $field_name;
313 $field_id = FrmField::create( $new_values );
314 return $field_id;
315 }
316
317 /**
318 * A credit card field is added automatically if missing before a Stripe action is updated.
319 *
320 * @param int $form_id
321 * @return int|false
322 */
323 private static function add_a_credit_card_field( $form_id ) {
324 return self::add_a_field( $form_id, 'credit_card', __( 'Payment', 'formidable' ) );
325 }
326
327 /**
328 * A gateway field is added automatically for compatibility with the Stripe add on.
329 * The gateway field is not important for the Stripe Lite implementation.
330 *
331 * @param int $form_id
332 * @return int|false
333 */
334 private static function add_a_gateway_field( $form_id ) {
335 return self::add_a_field( $form_id, 'gateway', __( 'Payment Method', 'formidable' ) );
336 }
337
338 /**
339 * Create any required Stripe plans, used for subscriptions.
340 *
341 * @param array $settings
342 * @return array
343 */
344 public static function create_plans( $settings ) {
345 if ( $settings['type'] !== 'recurring' || strpos( $settings['amount'], ']' ) ) {
346 // Don't create a plan for one time payments, or for actions with shortcodes in the value.
347 $settings['plan_id'] = '';
348 return $settings;
349 }
350
351 $plan_opts = FrmStrpLiteSubscriptionHelper::prepare_plan_options( $settings );
352 if ( $plan_opts['id'] != $settings['plan_id'] ) {
353 $settings['plan_id'] = FrmStrpLiteSubscriptionHelper::maybe_create_plan( $plan_opts );
354 }
355
356 return $settings;
357 }
358
359 /**
360 * Include settings in the plan description in order to make sure the correct plan is used.
361 *
362 * @param array $settings
363 * @return string
364 */
365 public static function create_plan_id( $settings ) {
366 $amount = self::prepare_amount( $settings['amount'], $settings );
367 $id = sanitize_title_with_dashes( $settings['description'] ) . '_' . $amount . '_' . $settings['interval_count'] . $settings['interval'] . '_' . $settings['currency'];
368 return $id;
369 }
370
371 /**
372 * If this form submits with ajax, load the scripts on the first page.
373 *
374 * @param array $params
375 * @return void
376 */
377 public static function maybe_load_scripts( $params ) {
378 if ( $params['form_id'] == $params['posted_form_id'] ) {
379 // This form has already been posted, so we aren't on the first page.
380 return;
381 }
382
383 $form = FrmForm::getOne( $params['form_id'] );
384 if ( ! $form ) {
385 return;
386 }
387
388 $credit_card_field = FrmField::getAll(
389 array(
390 'fi.form_id' => $form->id,
391 'type' => 'credit_card',
392 )
393 );
394 if ( ! $credit_card_field ) {
395 return;
396 }
397
398 self::load_scripts( (int) $form->id );
399 }
400
401 /**
402 * Load front end JavaScript for a Stripe form.
403 *
404 * @param int $form_id
405 * @return void
406 */
407 public static function load_scripts( $form_id ) {
408 if ( FrmAppHelper::is_admin_page( 'formidable-entries' ) ) {
409 return;
410 }
411
412 if ( wp_script_is( 'formidable-stripe', 'enqueued' ) ) {
413 return;
414 }
415
416 $stripe_connect_is_setup = FrmStrpLiteConnectHelper::stripe_connect_is_setup();
417 if ( ! $stripe_connect_is_setup ) {
418 return;
419 }
420
421 if ( ! $form_id || ! is_int( $form_id ) ) {
422 _doing_it_wrong( __METHOD__, '$form_id parameter must be a non-zero integer', 'x.x' );
423 return;
424 }
425
426 $settings = FrmStrpLiteAppHelper::get_settings();
427 $publishable = $settings->get_active_publishable_key();
428
429 wp_register_script(
430 'stripe',
431 'https://js.stripe.com/v3/',
432 array(),
433 '3.0',
434 false
435 );
436
437 $suffix = FrmAppHelper::js_suffix();
438 $dependencies = array( 'stripe', 'formidable' );
439
440 if ( '.min' === $suffix && is_readable( FrmAppHelper::plugin_path() . '/js/frmstrp.min.js' ) ) {
441 // Use the combined file if it is available.
442 $script_url = FrmAppHelper::plugin_url() . '/js/frmstrp.min.js';
443 } else {
444 if ( ! $suffix && ! is_readable( FrmStrpLiteAppHelper::plugin_path() . 'js/frmstrp.js' ) ) {
445 // The unminified file is not included in releases so force the minified script.
446 $suffix = '.min';
447 }
448 $script_url = FrmStrpLiteAppHelper::plugin_url() . 'js/frmstrp' . $suffix . '.js';
449 }
450
451 if ( class_exists( 'FrmProStrpLiteController' ) && ( ! $suffix || ! FrmProAppController::has_combo_js_file() ) ) {
452 $dependencies[] = 'formidablepro';
453 }
454
455 wp_enqueue_script(
456 'formidable-stripe',
457 $script_url,
458 $dependencies,
459 FrmAppHelper::plugin_version(),
460 false
461 );
462
463 $action_settings = self::prepare_settings_for_js( $form_id );
464 $style_settings = self::get_style_settings_for_form( $form_id );
465 $stripe_vars = array(
466 'publishable_key' => $publishable,
467 'form_id' => $form_id,
468 'nonce' => wp_create_nonce( 'frm_strp_ajax' ),
469 'ajax' => esc_url_raw( FrmAppHelper::get_ajax_url() ),
470 'settings' => $action_settings,
471 'locale' => self::get_locale(),
472 'baseFontSize' => $style_settings['field_font_size'],
473 'appearanceRules' => self::get_appearance_rules( $style_settings ),
474 'account_id' => FrmStrpLiteConnectHelper::get_account_id(),
475 );
476
477 wp_localize_script( 'formidable-stripe', 'frm_stripe_vars', $stripe_vars );
478 }
479
480 /**
481 * Get and format the style settings for JavaScript to use with the get_appearance_rules function.
482 *
483 * @since 6.5, introduced in v3.0 of the Stripe add on.
484 *
485 * @param mixed $form_id
486 * @return array
487 */
488 private static function get_style_settings_for_form( $form_id ) {
489 if ( ! $form_id ) {
490 return array();
491 }
492
493 $style = FrmStylesController::get_form_style( $form_id );
494 if ( ! $style ) {
495 return array();
496 }
497
498 $settings = FrmStylesHelper::get_settings_for_output( $style );
499 $disallowed = array( ';', ':', '!important' );
500 foreach ( $settings as $k => $s ) {
501 if ( is_string( $s ) ) {
502 $settings[ $k ] = str_replace( $disallowed, '', $s );
503 }
504 }
505
506 return $settings;
507 }
508
509 /**
510 * Get the style rules for Stripe link Authentication and Payment elements.
511 * These settings get set to frm_stripe_vars.appearanceRules.
512 * They're in the format that Stripe accepts.
513 * Documentation for Appearance rules can be found at https://stripe.com/docs/elements/appearance-api?platform=web#rules
514 *
515 * @since 6.5, introduced in v3.0 of the Stripe add on.
516 *
517 * @param array $settings
518 * @return array
519 */
520 private static function get_appearance_rules( $settings ) {
521 return array(
522 '.Input' => array(
523 'color' => $settings['text_color'],
524 'backgroundColor' => $settings['bg_color'],
525 'padding' => $settings['field_pad'],
526 'lineHeight' => 1.3,
527 'borderColor' => $settings['border_color'],
528 'borderWidth' => $settings['field_border_width'],
529 'borderStyle' => $settings['field_border_style'],
530 ),
531 '.Input::placeholder' => array(
532 'color' => $settings['text_color_disabled'],
533 ),
534 '.Input:focus' => array(
535 'backgroundColor' => $settings['bg_color_active'],
536 ),
537 '.Label' => array(
538 'color' => $settings['label_color'],
539 'fontSize' => $settings['font_size'],
540 'fontWeight' => $settings['weight'],
541 ),
542 '.Error' => array(
543 'color' => $settings['border_color_error'],
544 ),
545 );
546 }
547
548 /**
549 * Get the language to use for Stripe elements.
550 *
551 * @since 6.5, introduced in v2.0 of the Stripe add on.
552 * @return string
553 */
554 private static function get_locale() {
555 $allowed = array( 'ar', 'da', 'de', 'en', 'es', 'fi', 'fr', 'he', 'it', 'ja', 'nl', 'no', 'pl', 'ru', 'sv', 'zh' );
556 $current = get_locale();
557 $parts = explode( '_', $current );
558 $part = strtolower( $parts[0] );
559 return in_array( $part, $allowed, true ) ? $part : 'auto';
560 }
561
562 }
563