PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.13.3
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.13.3
3.13.3 3.13.2 3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 2.8.16 All 261 releases
← All changes | includes/core/widgets/bricks/class-offer-button.php +398 -14 3.10.6 → 3.13.3 View file →
@@ -16,9 +16,9 @@
16 16
17 17 public $category = 'wpfunnels';
18 18 public $name = 'wpfnl-offer-button';
19 19 public $icon = 'ti-mouse';
20 - public $css_selector = '.wpfnl-offerbtn-wrapper';
20 + public $css_selector = '.wpfnl-offerbtn-wrapper .wpfunnels_offer_button';
21 21 public $scripts = ['wpfnlOffer'];
22 22
23 23 /**
24 24 * Get element label
@@ -29,8 +29,27 @@
29 29 return esc_html__( 'Offer Button', 'wpfnl' );
30 30 }
31 31
32 32 /**
33 + * Get WordPress user roles for display condition control.
34 + *
35 + * @return array
36 + */
37 + protected function get_wp_user_roles() {
38 + $roles = [ 'none' => esc_html__( 'None', 'wpfnl' ) ];
39 +
40 + if ( ! function_exists( 'get_editable_roles' ) ) {
41 + require_once ABSPATH . 'wp-admin/includes/user.php';
42 + }
43 +
44 + foreach ( get_editable_roles() as $role_key => $role_info ) {
45 + $roles[ $role_key ] = $role_info['name'];
46 + }
47 +
48 + return $roles;
49 + }
50 +
51 + /**
33 52 * Set control groups
34 53 */
35 54 public function set_control_groups() {
36 55 $this->control_groups['settings'] = [
@@ -37,11 +56,12 @@
37 56 'title' => esc_html__( 'Settings', 'wpfnl' ),
38 57 'tab' => 'content',
39 58 ];
40 59
41 - $this->control_groups['style'] = [
42 - 'title' => esc_html__( 'Style', 'wpfnl' ),
43 - 'tab' => 'content',
60 + $this->control_groups['subtitle_style'] = [
61 + 'title' => esc_html__( 'Subtitle Style', 'wpfnl' ),
62 + 'tab' => 'content',
63 + 'required' => [ 'enable_subtitle', '=', true ],
44 64 ];
45 65 }
46 66
47 67 /**
@@ -96,8 +116,272 @@
96 116 ],
97 117 'inline' => true,
98 118 'default' => 'left',
99 119 ];
120 +
121 + // ---- Icon ----
122 + $this->controls['iconSeparator'] = [
123 + 'tab' => 'content',
124 + 'group' => 'settings',
125 + 'type' => 'separator',
126 + 'label' => esc_html__( 'Icon', 'wpfnl' ),
127 + ];
128 +
129 + $this->controls['icon'] = [
130 + 'tab' => 'content',
131 + 'group' => 'settings',
132 + 'label' => esc_html__( 'Icon', 'wpfnl' ),
133 + 'type' => 'icon',
134 + ];
135 +
136 + $this->controls['iconPosition'] = [
137 + 'tab' => 'content',
138 + 'group' => 'settings',
139 + 'label' => esc_html__( 'Icon Position', 'wpfnl' ),
140 + 'type' => 'select',
141 + 'options' => $this->control_options['iconPosition'],
142 + 'inline' => true,
143 + 'placeholder' => esc_html__( 'Right', 'wpfnl' ),
144 + 'required' => [ 'icon', '!=', '' ],
145 + ];
146 +
147 + // ---- Subtitle ----
148 + $this->controls['subtitleSeparator'] = [
149 + 'tab' => 'content',
150 + 'group' => 'settings',
151 + 'type' => 'separator',
152 + 'label' => esc_html__( 'Subtitle', 'wpfnl' ),
153 + ];
154 +
155 + $this->controls['enable_subtitle'] = [
156 + 'tab' => 'content',
157 + 'group' => 'settings',
158 + 'label' => esc_html__( 'Enable Subtitle', 'wpfnl' ),
159 + 'type' => 'checkbox',
160 + 'default' => false,
161 + ];
162 +
163 + $this->controls['subtitle_text'] = [
164 + 'tab' => 'content',
165 + 'group' => 'settings',
166 + 'label' => esc_html__( 'Subtitle Text', 'wpfnl' ),
167 + 'type' => 'text',
168 + 'default' => esc_html__( 'Click to continue', 'wpfnl' ),
169 + 'placeholder' => esc_html__( 'Enter subtitle text', 'wpfnl' ),
170 + 'required' => [ 'enable_subtitle', '=', true ],
171 + ];
172 +
173 + // ---- Subtitle Style (group) ----
174 + $this->controls['subtitleTypography'] = [
175 + 'tab' => 'content',
176 + 'group' => 'subtitle_style',
177 + 'label' => esc_html__( 'Subtitle Typography', 'wpfnl' ),
178 + 'type' => 'typography',
179 + 'css' => [
180 + [
181 + 'property' => 'font',
182 + 'selector' => '.wpfnl-button-subtitle',
183 + ],
184 + ],
185 + 'exclude' => [ 'text-align', 'text-decoration', 'line-height' ],
186 + ];
187 +
188 + $this->controls['subtitleSpacing'] = [
189 + 'tab' => 'content',
190 + 'group' => 'subtitle_style',
191 + 'label' => esc_html__( 'Subtitle Spacing Top', 'wpfnl' ),
192 + 'type' => 'number',
193 + 'units' => true,
194 + 'css' => [
195 + [
196 + 'property' => 'margin-top',
197 + 'selector' => '.wpfnl-button-subtitle',
198 + ],
199 + ],
200 + 'default' => '2px',
201 + ];
202 +
203 + // ---- Responsive Display ----
204 + $this->controls['responsiveSeparator'] = [
205 + 'tab' => 'content',
206 + 'group' => 'settings',
207 + 'label' => esc_html__( 'Responsive Display', 'wpfnl' ),
208 + 'type' => 'separator',
209 + ];
210 +
211 + $this->controls['hide_on_desktop'] = [
212 + 'tab' => 'content',
213 + 'group' => 'settings',
214 + 'label' => esc_html__( 'Hide on Desktop (≥ 1200px)', 'wpfnl' ),
215 + 'type' => 'checkbox',
216 + 'default' => false,
217 + 'description' => esc_html__( 'Hide button on desktop devices (window width >= 1200px)', 'wpfnl' ),
218 + ];
219 +
220 + $this->controls['hide_on_tablet'] = [
221 + 'tab' => 'content',
222 + 'group' => 'settings',
223 + 'label' => esc_html__( 'Hide on Tablet (768px – 1199px)', 'wpfnl' ),
224 + 'type' => 'checkbox',
225 + 'default' => false,
226 + 'description' => esc_html__( 'Hide button on tablet devices (window width 768px - 1199px)', 'wpfnl' ),
227 + ];
228 +
229 + $this->controls['hide_on_mobile'] = [
230 + 'tab' => 'content',
231 + 'group' => 'settings',
232 + 'label' => esc_html__( 'Hide on Mobile (≤ 767px)', 'wpfnl' ),
233 + 'type' => 'checkbox',
234 + 'default' => false,
235 + 'description' => esc_html__( 'Hide button on mobile devices (window width <= 767px)', 'wpfnl' ),
236 + ];
237 +
238 + // ---- Display Conditions ----
239 + $this->controls['displayConditionSeparator'] = [
240 + 'tab' => 'content',
241 + 'group' => 'settings',
242 + 'label' => esc_html__( 'Display Conditions', 'wpfnl' ),
243 + 'type' => 'separator',
244 + ];
245 +
246 + $this->controls['display_condition_type'] = [
247 + 'tab' => 'content',
248 + 'group' => 'settings',
249 + 'label' => esc_html__( 'Display Condition', 'wpfnl' ),
250 + 'type' => 'select',
251 + 'options' => [
252 + 'none' => esc_html__( 'None', 'wpfnl' ),
253 + 'user_state' => esc_html__( 'User State', 'wpfnl' ),
254 + 'user_role' => esc_html__( 'User Role', 'wpfnl' ),
255 + 'browser' => esc_html__( 'Browser', 'wpfnl' ),
256 + 'operating_system' => esc_html__( 'Operating System', 'wpfnl' ),
257 + 'day' => esc_html__( 'Day', 'wpfnl' ),
258 + ],
259 + 'inline' => false,
260 + 'default' => 'none',
261 + ];
262 +
263 + $this->controls['hide_from_logged_in'] = [
264 + 'tab' => 'content',
265 + 'group' => 'settings',
266 + 'label' => esc_html__( 'Hide From Logged In User', 'wpfnl' ),
267 + 'type' => 'checkbox',
268 + 'default' => false,
269 + 'required' => [ 'display_condition_type', '=', 'user_state' ],
270 + ];
271 +
272 + $this->controls['hide_from_logged_out'] = [
273 + 'tab' => 'content',
274 + 'group' => 'settings',
275 + 'label' => esc_html__( 'Hide From Logged Out User', 'wpfnl' ),
276 + 'type' => 'checkbox',
277 + 'default' => false,
278 + 'required' => [ 'display_condition_type', '=', 'user_state' ],
279 + ];
280 +
281 + $this->controls['hide_for_user_role'] = [
282 + 'tab' => 'content',
283 + 'group' => 'settings',
284 + 'label' => esc_html__( 'Hide For User Role', 'wpfnl' ),
285 + 'type' => 'select',
286 + 'options' => $this->get_wp_user_roles(),
287 + 'default' => 'none',
288 + 'required' => [ 'display_condition_type', '=', 'user_role' ],
289 + ];
290 +
291 + $this->controls['hide_on_browser'] = [
292 + 'tab' => 'content',
293 + 'group' => 'settings',
294 + 'label' => esc_html__( 'Hide On Browser', 'wpfnl' ),
295 + 'type' => 'select',
296 + 'options' => [
297 + 'none' => esc_html__( 'None', 'wpfnl' ),
298 + 'mozilla' => esc_html__( 'Mozilla Firefox', 'wpfnl' ),
299 + 'chrome' => esc_html__( 'Google Chrome', 'wpfnl' ),
300 + 'opera_mini' => esc_html__( 'Opera Mini', 'wpfnl' ),
301 + 'safari' => esc_html__( 'Safari', 'wpfnl' ),
302 + 'edge' => esc_html__( 'Microsoft Edge', 'wpfnl' ),
303 + ],
304 + 'default' => 'none',
305 + 'required' => [ 'display_condition_type', '=', 'browser' ],
306 + ];
307 +
308 + $this->controls['hide_on_os'] = [
309 + 'tab' => 'content',
310 + 'group' => 'settings',
311 + 'label' => esc_html__( 'Hide On Operating System', 'wpfnl' ),
312 + 'type' => 'select',
313 + 'options' => [
314 + 'none' => esc_html__( 'None', 'wpfnl' ),
315 + 'ios' => esc_html__( 'iOS', 'wpfnl' ),
316 + 'android' => esc_html__( 'Android', 'wpfnl' ),
317 + 'windows' => esc_html__( 'Windows', 'wpfnl' ),
318 + 'macos' => esc_html__( 'MacOS', 'wpfnl' ),
319 + 'linux' => esc_html__( 'Linux', 'wpfnl' ),
320 + 'sunos' => esc_html__( 'SunOS', 'wpfnl' ),
321 + 'openbsd' => esc_html__( 'OpenBSD', 'wpfnl' ),
322 + ],
323 + 'default' => 'none',
324 + 'required' => [ 'display_condition_type', '=', 'operating_system' ],
325 + ];
326 +
327 + $this->controls['disable_on_days'] = [
328 + 'tab' => 'content',
329 + 'group' => 'settings',
330 + 'label' => esc_html__( 'Select Days You Want To Disable', 'wpfnl' ),
331 + 'type' => 'select',
332 + 'multiple' => true,
333 + 'options' => [
334 + 'monday' => esc_html__( 'Monday', 'wpfnl' ),
335 + 'tuesday' => esc_html__( 'Tuesday', 'wpfnl' ),
336 + 'wednesday' => esc_html__( 'Wednesday', 'wpfnl' ),
337 + 'thursday' => esc_html__( 'Thursday', 'wpfnl' ),
338 + 'friday' => esc_html__( 'Friday', 'wpfnl' ),
339 + 'saturday' => esc_html__( 'Saturday', 'wpfnl' ),
340 + 'sunday' => esc_html__( 'Sunday', 'wpfnl' ),
341 + ],
342 + 'default' => [],
343 + 'required' => [ 'display_condition_type', '=', 'day' ],
344 + ];
345 +
346 + // ---- Animation ----
347 + $this->controls['animationSeparator'] = [
348 + 'tab' => 'content',
349 + 'group' => 'settings',
350 + 'label' => esc_html__( 'Animation', 'wpfnl' ),
351 + 'type' => 'separator',
352 + ];
353 +
354 + $this->controls['entrance_animation'] = [
355 + 'tab' => 'content',
356 + 'group' => 'settings',
357 + 'label' => esc_html__( 'Entrance Animation', 'wpfnl' ),
358 + 'type' => 'select',
359 + 'options' => [
360 + '' => esc_html__( 'None', 'wpfnl' ),
361 + 'fadeIn' => esc_html__( 'Fade In', 'wpfnl' ),
362 + 'fadeInUp' => esc_html__( 'Fade In Up', 'wpfnl' ),
363 + 'fadeInDown' => esc_html__( 'Fade In Down', 'wpfnl' ),
364 + 'fadeInLeft' => esc_html__( 'Fade In Left', 'wpfnl' ),
365 + 'fadeInRight' => esc_html__( 'Fade In Right', 'wpfnl' ),
366 + 'zoomIn' => esc_html__( 'Zoom In', 'wpfnl' ),
367 + 'zoomInUp' => esc_html__( 'Zoom In Up', 'wpfnl' ),
368 + 'bounceIn' => esc_html__( 'Bounce In', 'wpfnl' ),
369 + 'bounceInUp' => esc_html__( 'Bounce In Up', 'wpfnl' ),
370 + 'slideInUp' => esc_html__( 'Slide In Up', 'wpfnl' ),
371 + 'slideInLeft' => esc_html__( 'Slide In Left', 'wpfnl' ),
372 + 'slideInRight'=> esc_html__( 'Slide In Right', 'wpfnl' ),
373 + 'flipInX' => esc_html__( 'Flip In X', 'wpfnl' ),
374 + 'flipInY' => esc_html__( 'Flip In Y', 'wpfnl' ),
375 + 'pulse' => esc_html__( 'Pulse', 'wpfnl' ),
376 + 'tada' => esc_html__( 'Tada', 'wpfnl' ),
377 + 'wobble' => esc_html__( 'Wobble', 'wpfnl' ),
378 + ],
379 + 'inline' => false,
380 + 'placeholder' => esc_html__( 'None', 'wpfnl' ),
381 + 'default' => '',
382 + 'description' => esc_html__( 'Animation plays when the button enters the viewport on the live page.', 'wpfnl' ),
383 + ];
100 384 }
101 385
102 386 /**
103 387 * Render element
@@ -103,18 +387,92 @@
103 387 * Render element
104 388 */
105 389 public function render() {
106 390 $settings = $this->settings;
107 -
108 - $offer_action = isset( $settings['offerAction'] ) ? $settings['offerAction'] : 'accept';
109 - $button_text = isset( $settings['buttonText'] ) ? $settings['buttonText'] : __( 'Yes, Add to My Order!', 'wpfnl' );
110 - $show_price = isset( $settings['showProductPrice'] ) ? $settings['showProductPrice'] : 'no';
111 - $button_align = isset( $settings['buttonAlign'] ) ? $settings['buttonAlign'] : 'left';
112 -
113 - // Get offer button type from settings or URL
391 +
392 + // ---- Display Conditions ----
393 + $display_condition = ! empty( $settings['display_condition_type'] ) ? $settings['display_condition_type'] : 'none';
394 +
395 + if ( $display_condition === 'user_state' ) {
396 + $hide_logged_in = ! empty( $settings['hide_from_logged_in'] );
397 + $hide_logged_out = ! empty( $settings['hide_from_logged_out'] );
398 + if ( $hide_logged_in && is_user_logged_in() ) { return; }
399 + if ( $hide_logged_out && ! is_user_logged_in() ) { return; }
400 +
401 + } elseif ( $display_condition === 'user_role' ) {
402 + $hide_for_user_role = ! empty( $settings['hide_for_user_role'] ) ? $settings['hide_for_user_role'] : 'none';
403 + if ( $hide_for_user_role !== 'none' && is_user_logged_in() ) {
404 + $user = wp_get_current_user();
405 + if ( in_array( $hide_for_user_role, $user->roles ) ) { return; }
406 + }
407 +
408 + } elseif ( $display_condition === 'day' ) {
409 + $disable_on_days = ! empty( $settings['disable_on_days'] ) ? $settings['disable_on_days'] : [];
410 + if ( ! empty( $disable_on_days ) && is_array( $disable_on_days ) ) {
411 + if ( in_array( strtolower( date( 'l' ) ), $disable_on_days ) ) { return; }
412 + }
413 +
414 + } elseif ( $display_condition === 'browser' ) {
415 + $hide_on_browser = ! empty( $settings['hide_on_browser'] ) ? $settings['hide_on_browser'] : 'none';
416 + if ( $hide_on_browser !== 'none' ) {
417 + $ua = isset( $_SERVER['HTTP_USER_AGENT'] ) ? strtolower( $_SERVER['HTTP_USER_AGENT'] ) : '';
418 + $cb = '';
419 + if ( strpos( $ua, 'edg' ) !== false ) { $cb = 'edge'; }
420 + elseif ( strpos( $ua, 'opr' ) !== false || strpos( $ua, 'opera' ) !== false ) { $cb = 'opera_mini'; }
421 + elseif ( strpos( $ua, 'chrome' ) !== false ) { $cb = 'chrome'; }
422 + elseif ( strpos( $ua, 'safari' ) !== false ) { $cb = 'safari'; }
423 + elseif ( strpos( $ua, 'firefox' ) !== false ) { $cb = 'mozilla'; }
424 + if ( $cb === $hide_on_browser ) { return; }
425 + }
426 +
427 + } elseif ( $display_condition === 'operating_system' ) {
428 + $hide_on_os = ! empty( $settings['hide_on_os'] ) ? $settings['hide_on_os'] : 'none';
429 + if ( $hide_on_os !== 'none' ) {
430 + $ua = isset( $_SERVER['HTTP_USER_AGENT'] ) ? strtolower( $_SERVER['HTTP_USER_AGENT'] ) : '';
431 + $co = '';
432 + if ( strpos( $ua, 'windows' ) !== false || strpos( $ua, 'win32' ) !== false || strpos( $ua, 'win64' ) !== false ) { $co = 'windows'; }
433 + elseif ( strpos( $ua, 'macintosh' ) !== false || strpos( $ua, 'mac os x' ) !== false ) { $co = 'macos'; }
434 + elseif ( strpos( $ua, 'linux' ) !== false && strpos( $ua, 'android' ) === false ) { $co = 'linux'; }
435 + elseif ( strpos( $ua, 'android' ) !== false ) { $co = 'android'; }
436 + elseif ( strpos( $ua, 'iphone' ) !== false || strpos( $ua, 'ipad' ) !== false || strpos( $ua, 'ipod' ) !== false ) { $co = 'ios'; }
437 + elseif ( strpos( $ua, 'sunos' ) !== false ) { $co = 'sunos'; }
438 + elseif ( strpos( $ua, 'openbsd' ) !== false ) { $co = 'openbsd'; }
439 + if ( $co === $hide_on_os ) { return; }
440 + }
441 + }
442 + // ---- End Display Conditions ----
443 +
444 + $offer_action = isset( $settings['offerAction'] ) ? $settings['offerAction'] : 'accept';
445 + $button_text = isset( $settings['buttonText'] ) ? $settings['buttonText'] : __( 'Yes, Add to My Order!', 'wpfnl' );
446 + $show_price = isset( $settings['showProductPrice'] ) ? $settings['showProductPrice'] : 'no';
447 + $button_align = isset( $settings['buttonAlign'] ) ? $settings['buttonAlign'] : 'left';
114 448 $offer_button_type = isset( $settings['offerType'] ) ? $settings['offerType'] : 'upsell';
115 -
449 +
450 + // Animation
451 + $animation = ! empty( $settings['entrance_animation'] ) ? $settings['entrance_animation'] : '';
452 + $animation_class = $animation ? ' wpfnl-animation ' . esc_attr( $animation ) : '';
453 +
454 + $is_bricks_editor = isset( $_GET['bricks'] ) && 'run' === $_GET['bricks'];
455 + $bricks_editor_class = $is_bricks_editor ? 'bricks-editor-active' : '';
456 +
116 457 $this->set_attribute( '_root', 'class', 'wp-block-wpfnl-offer-btn-' . esc_attr( $button_align ) );
458 + if ( $animation ) {
459 + $this->set_attribute( '_root', 'class', 'wpfnl-animation ' . esc_attr( $animation ) );
460 + }
461 + if ( $is_bricks_editor ) {
462 + $this->set_attribute( '_root', 'class', 'bricks-editor-active' );
463 + }
464 +
465 + // Responsive display classes
466 + if ( ! empty( $settings['hide_on_desktop'] ) ) {
467 + $this->set_attribute( '_root', 'class', 'wpfnl-hide-desktop' );
468 + }
469 + if ( ! empty( $settings['hide_on_tablet'] ) ) {
470 + $this->set_attribute( '_root', 'class', 'wpfnl-hide-tablet' );
471 + }
472 + if ( ! empty( $settings['hide_on_mobile'] ) ) {
473 + $this->set_attribute( '_root', 'class', 'wpfnl-hide-mobile' );
474 + }
117 475
118 476 // Get product data
119 477 $response = \WPFunnels\Wpfnl_functions::get_product_data_for_widget( get_the_ID() );
120 478 $offer_product = isset($response['offer_product']) && $response['offer_product'] ? $response['offer_product'] : '';
@@ -159,12 +517,38 @@
159 517 </span>
160 518 <?php endif; ?>
161 519
162 520 <a href="#"
163 - class="wpfunnels-bricks-widget wpfunnels_offer_button btn"
521 + class="wpfunnels-bricks-widget wpfunnels_offer_button btn<?php echo ( ! empty( $settings['enable_subtitle'] ) && ! empty( $settings['subtitle_text'] ) ) ? ' wpfnl-has-subtitle' : ''; ?>"
164 522 id="wpfunnels_<?php echo esc_attr( $offer_button_type ); ?>_<?php echo esc_attr( $offer_action ); ?>"
165 523 data-offertype="<?php echo esc_attr( $offer_button_type ); ?>">
166 - <?php echo esc_html( $button_text ); ?>
524 + <?php
525 + $icon = ! empty( $settings['icon'] ) ? self::render_icon( $settings['icon'] ) : false;
526 + $icon_position = ! empty( $settings['iconPosition'] ) ? $settings['iconPosition'] : 'right';
527 + $enable_subtitle = ! empty( $settings['enable_subtitle'] );
528 + $subtitle_text = ! empty( $settings['subtitle_text'] ) ? $settings['subtitle_text'] : '';
529 +
530 + if ( $enable_subtitle && $subtitle_text ) {
531 + echo "<span class='icon-wrapper'>";
532 + if ( $icon && $icon_position === 'left' ) {
533 + echo $icon;
534 + }
535 + echo esc_html( $button_text );
536 + if ( $icon && $icon_position === 'right' ) {
537 + echo $icon;
538 + }
539 + echo "</span>";
540 + echo '<small class="wpfnl-button-subtitle">' . esc_html( $subtitle_text ) . '</small>';
541 + } else {
542 + if ( $icon && $icon_position === 'left' ) {
543 + echo $icon;
544 + }
545 + echo esc_html( $button_text );
546 + if ( $icon && $icon_position === 'right' ) {
547 + echo $icon;
548 + }
549 + }
550 + ?>
167 551 </a>
168 552 </div>
169 553
170 554 <?php