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 | classes/models/FrmSalesApi.php +54 -140 6.26 → trunk View file →
@@ -29,45 +29,40 @@
29 29 */
30 30 private static $best_sale;
31 31
32 32 /**
33 - * @since 6.25.1
33 + * Flag to prevent the $this->set_sales() call in the constructor.
34 34 *
35 - * @var string|null
36 - */
37 - private static $cross_sell_text;
38 -
39 - /**
40 - * @since 6.25.1
35 + * @since 6.34
41 36 *
42 - * @var string|null
37 + * @var bool
43 38 */
44 - private static $cross_sell_link;
39 + private static $prevent_new_sales_request = false;
45 40
46 41 public function __construct() {
47 42 $this->set_cache_key();
48 43
49 - if ( false === self::$sales ) {
44 + if ( ! self::$prevent_new_sales_request && false === self::$sales ) {
50 45 $this->set_sales();
51 46 }
52 47 }
53 48
54 49 /**
55 - * @since 6.17
50 + * @since 6.34
56 51 *
57 52 * @return void
58 53 */
59 - protected function set_cache_key() {
60 - $this->cache_key = 'frm_sales_cache';
54 + public static function prevent_new_sales_requests() {
55 + self::$prevent_new_sales_request = true;
61 56 }
62 57
63 58 /**
64 - * @since 6.17
59 + * @since 6.34
65 60 *
66 - * @return string
61 + * @return void
67 62 */
68 - protected function api_url() {
69 - return 'https://plapi.formidableforms.com/sales/';
63 + public static function allow_new_sales_requests() {
64 + self::$prevent_new_sales_request = false;
70 65 }
71 66
72 67 /**
73 68 * @since 6.17
@@ -73,111 +68,55 @@
73 68 * @since 6.17
74 69 *
75 70 * @return void
76 71 */
77 - private function set_sales() {
78 - self::$sales = array();
79 -
80 - $api = $this->get_api_info();
81 -
82 - if ( empty( $api ) ) {
83 - return;
84 - }
85 -
86 - foreach ( $api as $sale ) {
87 - $this->add_sale( $sale );
88 -
89 - if ( is_array( $sale ) && isset( $sale['cross_sell_text'] ) ) {
90 - $this->set_cross_sell( $sale );
91 - }
92 - }
72 + protected function set_cache_key() {
73 + $this->cache_key = 'frm_sales_cache';
93 74 }
94 75
95 76 /**
96 - * Check for a special array in the sales API array.
97 - * Normally cross_sell_text and cross_sell_link are not set.
98 - * But one array, that isn't actually a sale, contains cross sell data.
99 - * This should be near the end of the array.
77 + * @since 6.17
100 78 *
101 - * @since 6.25.1
102 - *
103 - * @param array $data
104 - *
105 - * @return void
79 + * @return string
106 80 */
107 - private function set_cross_sell( $data ) {
108 - if ( ! self::cross_sell_is_valid( $data ) ) {
109 - return;
110 - }
111 -
112 - $cross_sell_text = $data['cross_sell_text'];
113 - $cross_sell_links = $data['cross_sell_link'];
114 - $index = self::determine_cross_sell_index( $cross_sell_text );
115 -
116 - self::$cross_sell_text = sanitize_text_field( $cross_sell_text[ $index ] );
117 - self::$cross_sell_link = esc_url_raw( $cross_sell_links[ $index ] );
81 + protected function api_url() {
82 + return 'https://plapi.formidableforms.com/sales/';
118 83 }
119 84
120 85 /**
121 - * Check that both cross_sell_text and cross_sell_link are set and are arrays of the same size.
86 + * If the last check was a rate limit, we'll need to check again sooner.
87 + * Other APIs use the FrmFormApi function which uses a 5 minute timeout. But for Sales, we can use 1 hour.
122 88 *
123 - * @since 6.25.1
89 + * @since 6.32
124 90 *
125 - * @param array $data
91 + * @param array $addons
126 92 *
127 - * @return bool
93 + * @return string
128 94 */
129 - private function cross_sell_is_valid( $data ) {
130 - if ( empty( $data['cross_sell_text'] ) || empty( $data['cross_sell_link'] ) ) {
131 - return false;
95 + protected function get_cache_timeout( $addons ) {
96 + if ( isset( $addons['response_code'] ) && 429 === $addons['response_code'] ) {
97 + return '+1 hour';
132 98 }
133 -
134 - if ( ! is_array( $data['cross_sell_text'] ) || ! is_array( $data['cross_sell_link'] ) ) {
135 - return false;
136 - }
137 -
138 - return count( $data['cross_sell_link'] ) === count( $data['cross_sell_text'] );
99 + return $this->cache_timeout;
139 100 }
140 101
141 102 /**
142 - * Determine which cross sell text to use.
143 - * These are shown in order for 30 days before moving on to the next one.
103 + * @since 6.17
144 104 *
145 - * @since 6.25.1
146 - *
147 - * @param array $cross_sell_text
148 - *
149 - * @return int
105 + * @return void
150 106 */
151 - private static function determine_cross_sell_index( $cross_sell_text ) {
152 - $option_name = 'frm_cross_sell_settings';
153 - $cross_sell_settings = get_option( $option_name );
107 + private function set_sales() {
108 + self::$sales = array();
154 109
155 - if ( ! is_array( $cross_sell_settings ) ) {
156 - $cross_sell_settings = array(
157 - reset( $cross_sell_text ) => time(),
158 - );
159 - update_option( $option_name, $cross_sell_settings );
160 - return 0;
110 + $api = $this->get_api_info();
111 +
112 + if ( ! $api ) {
113 + return;
161 114 }
162 115
163 - foreach ( $cross_sell_text as $index => $current_text ) {
164 - if ( ! isset( $cross_sell_settings[ $current_text ] ) ) {
165 - $cross_sell_settings[ $current_text ] = time();
166 - update_option( $option_name, $cross_sell_settings );
167 - return $index;
168 - }
169 -
170 - $time_elapsed = time() - $cross_sell_settings[ $current_text ];
171 -
172 - if ( $time_elapsed < DAY_IN_SECONDS * 30 ) {
173 - return $index;
174 - }
116 + foreach ( $api as $sale ) {
117 + $this->add_sale( $sale );
175 118 }
176 -
177 - // If all options are expired, reset the option.
178 - delete_option( $option_name );
179 - return 0;
180 119 }
181 120
182 121 /**
183 122 * @param array|string $sale
@@ -191,10 +130,10 @@
191 130 return;
192 131 }
193 132
194 133 if ( ! is_array( $sale ) || ! isset( $sale['key'] ) ) {
195 - // if the API response is invalid, $sale may not be an array.
196 - // if there are no sales from the API, it is returning a "No Entries Found" item with no key, so check for a key as well.
134 + // If the API response is invalid, $sale may not be an array.
135 + // If there are no sales from the API, it is returning a "No Entries Found" item with no key, so check for a key as well.
197 136 return;
198 137 }
199 138
200 139 if ( ! $this->sale_is_active( $sale ) ) {
@@ -311,9 +250,19 @@
311 250 }
312 251
313 252 $sale = self::$instance->get_best_sale();
314 253
315 - return is_array( $sale ) && ! empty( $sale[ $key ] ) ? $sale[ $key ] : false;
254 + if ( ! is_array( $sale ) || empty( $sale[ $key ] ) ) {
255 + return false;
256 + }
257 +
258 + $sale_value = $sale[ $key ];
259 +
260 + if ( str_ends_with( $key, '_link' ) && ! str_starts_with( $sale_value, 'https://formidableforms.com' ) ) {
261 + return false;
262 + }
263 +
264 + return $sale_value;
316 265 }
317 266
318 267 /**
319 268 * @since 6.17
@@ -344,8 +293,9 @@
344 293 // Generate either 0 or 1.
345 294 $option = mt_rand( 0, 1 );
346 295 update_option( 'frm_sale_ab_group', $option, false );
347 296 }
297 +
348 298 return (int) $option;
349 299 }
350 300
351 301 /**
@@ -435,8 +385,9 @@
435 385 $content_attrs['style'] = 'color: ' . esc_attr( $banner_text_color ) . ';';
436 386 $dismiss_attrs['style'] = 'color: ' . esc_attr( $banner_text_color ) . ';';
437 387 }
438 388
389 + // phpcs:disable Generic.WhiteSpace.ScopeIndent
439 390 ?>
440 391 <div <?php FrmAppHelper::array_to_html_params( $banner_attrs, true ); ?>>
441 392 <div>
442 393 <img src="<?php echo esc_url( FrmAppHelper::plugin_url() . '/images/sales/' . $banner_icon . '.svg' ); ?>" alt="<?php echo esc_attr( $banner_title ); ?>" />
@@ -453,11 +404,12 @@
453 404 <a <?php FrmAppHelper::array_to_html_params( $cta_attrs, true ); ?>>
454 405 <?php echo esc_html( $banner_cta_text ); ?>
455 406 </a>
456 407 </div>
457 - <a <?php FrmAppHelper::array_to_html_params( $dismiss_attrs, true ); ?>><?php FrmAppHelper::icon_by_class( 'frm_icon_font frm_close_icon' ); ?></a>
408 + <a <?php FrmAppHelper::array_to_html_params( $dismiss_attrs, true ); ?>><?php FrmAppHelper::icon_by_class( 'frmfont frm_close_icon' ); ?></a>
458 409 </div>
459 410 <?php
411 + // phpcs:enable Generic.WhiteSpace.ScopeIndent
460 412
461 413 return true;
462 414 }
463 415
@@ -499,44 +451,6 @@
499 451 */
500 452 private static function is_banner_dismissed( $key ) {
501 453 $dismissed_sales = get_user_option( 'frm_dismissed_sales', get_current_user_id() );
502 454 return is_array( $dismissed_sales ) && in_array( $key, $dismissed_sales, true );
503 - }
504 -
505 - /**
506 - * @return void
507 - */
508 - public static function menu() {
509 - if ( false === self::$sales ) {
510 - new self();
511 - }
512 -
513 - if ( ! self::$cross_sell_text || ! self::$cross_sell_link ) {
514 - return;
515 - }
516 -
517 - add_submenu_page(
518 - 'formidable',
519 - esc_html( self::$cross_sell_text ) . ' | Formidable',
520 - esc_html( self::$cross_sell_text ),
521 - 'activate_plugins',
522 - 'frm-sales-api-cross-sell',
523 - function () {
524 - // There is no page. The redirect logic is handled below, before this callback is triggered.
525 - }
526 - );
527 -
528 - add_action(
529 - 'admin_init',
530 - function () {
531 - if ( ! current_user_can( 'activate_plugins' ) ) {
532 - return;
533 - }
534 -
535 - if ( 'frm-sales-api-cross-sell' === FrmAppHelper::simple_get( 'page' ) && ! empty( self::$cross_sell_link ) ) {
536 - wp_redirect( self::$cross_sell_link );
537 - exit;
538 - }
539 - }
540 - );
541 455 }
542 456 }