← All changes
|
includes/Extensions/PopupNotification/PopupNotification.php
+336
-7
3.2.7
→
3.3.3
View file →
| @@ -126,9 +126,72 @@ | ||
| 126 | 126 | 'position' => 'center', |
| 127 | 127 | ], |
| 128 | 128 | 'column' => "5", |
| 129 | 129 | ], |
| 130 | - | |
| 130 | + // Coupon Popup card (light) — headline + description + copyable | |
| 131 | + // coupon code + "Get Coupon" CTA + dismiss link. | |
| 132 | + 'theme-eight' => [ | |
| 133 | + 'source' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/popup/popup-theme-eight.png', | |
| 134 | + 'defaults' => [ | |
| 135 | + 'popup_title' => __('35% OFF NOW', 'notificationx'), | |
| 136 | + 'popup_content' => __('Get an extra 35% off on all products!', 'notificationx'), | |
| 137 | + 'popup_coupon_code' => __('GET35OFF', 'notificationx'), | |
| 138 | + 'popup_button_text' => __('Get Coupon', 'notificationx'), | |
| 139 | + 'popup_button_url' => '#', | |
| 140 | + 'position' => 'center', | |
| 141 | + ], | |
| 142 | + 'column' => "5", | |
| 143 | + ], | |
| 144 | + // Festive/seasonal coupon popup — doodle-textured colored header | |
| 145 | + // with a wavy divider, big discount headline, an eyebrow tagline, | |
| 146 | + // a headline + copyable coupon code + soft dismiss link (no CTA). | |
| 147 | + 'theme-eleven' => [ | |
| 148 | + 'source' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/popup/popup-theme-eleven.png?v=2', | |
| 149 | + 'defaults' => [ | |
| 150 | + 'popup_subtitle' => __('Back to School Deal', 'notificationx'), | |
| 151 | + 'popup_title' => __('25% OFF!', 'notificationx'), | |
| 152 | + 'popup_content' => __('Get a ready-to-go healthy lunchbox kit', 'notificationx'), | |
| 153 | + 'popup_coupon_code' => __('BTS2025', 'notificationx'), | |
| 154 | + 'position' => 'center', | |
| 155 | + ], | |
| 156 | + 'column' => "5", | |
| 157 | + ], | |
| 158 | + // High-impact electronics flash-sale coupon popup — bold yellow | |
| 159 | + // card, a rotated "%OFF" sticker badge (subtitle = the big number), | |
| 160 | + // headline + subtext + copyable coupon code (no CTA / dismiss). | |
| 161 | + 'theme-twelve' => [ | |
| 162 | + 'source' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/popup/popup-theme-twelve.png', | |
| 163 | + 'defaults' => [ | |
| 164 | + 'popup_subtitle' => __('64%', 'notificationx'), | |
| 165 | + 'popup_title' => __('Enjoy 64% Electronics Sale', 'notificationx'), | |
| 166 | + 'popup_content' => __('Upgrade your gadgets at unbeatable prices.', 'notificationx'), | |
| 167 | + 'popup_coupon_code' => __('ELEC 4512658', 'notificationx'), | |
| 168 | + 'position' => 'center', | |
| 169 | + ], | |
| 170 | + 'column' => "5", | |
| 171 | + ], | |
| 172 | + // Multi-tier discount popup — gift hero, two-tone heading, a list of | |
| 173 | + // coupon "tickets" (percent + code + validity) and a "Claim Now" CTA. | |
| 174 | + 'theme-thirteen' => [ | |
| 175 | + 'source' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/popup/popup-theme-thirteen.png', | |
| 176 | + 'defaults' => [ | |
| 177 | + 'popup_title' => __('Buy Upto $500', 'notificationx'), | |
| 178 | + 'popup_subtitle' => __('And Get Discount Now', 'notificationx'), | |
| 179 | + 'popup_content' => __('Take discount in your next order', 'notificationx'), | |
| 180 | + 'popup_button_text' => __('Claim Now', 'notificationx'), | |
| 181 | + 'popup_button_url' => '#', | |
| 182 | + 'popup_coupon_repeater' => [ | |
| 183 | + [ | |
| 184 | + 'coupon_percent' => __('20%', 'notificationx'), | |
| 185 | + 'coupon_code' => __('#SAVE20', 'notificationx'), | |
| 186 | + 'coupon_validity' => __('Valid for 7 Days', 'notificationx'), | |
| 187 | + ], | |
| 188 | + ], | |
| 189 | + 'position' => 'center', | |
| 190 | + ], | |
| 191 | + 'column' => "5", | |
| 192 | + ], | |
| 193 | + | |
| 131 | 194 | ]; |
| 132 | 195 | } |
| 133 | 196 | |
| 134 | 197 | public function init_fields() { |
| @@ -583,10 +646,19 @@ | ||
| 583 | 646 | 'label' => __('Subtitle', 'notificationx'), |
| 584 | 647 | 'name' => 'popup_subtitle', |
| 585 | 648 | 'type' => 'text', |
| 586 | 649 | 'priority' => 12, |
| 587 | - 'default' => __('Would like to get the latest news & updates instantly?', 'notificationx'), | |
| 588 | - 'rules' => Rules::is('themes', 'popup_notification_theme-seven'), | |
| 650 | + // No global field-level default: a hardcoded value here pre-fills the | |
| 651 | + // field and blocks each theme's own `defaults` (subtitle) from applying | |
| 652 | + // on selection, so coupon themes (eleven/twelve/thirteen) inherited the | |
| 653 | + // wrong subtitle. Leave empty so the selected theme's default fills it. | |
| 654 | + 'default' => '', | |
| 655 | + 'rules' => Rules::logicalRule([ | |
| 656 | + Rules::is('themes', 'popup_notification_theme-seven'), | |
| 657 | + Rules::is('themes', 'popup_notification_theme-eleven'), | |
| 658 | + Rules::is('themes', 'popup_notification_theme-twelve'), | |
| 659 | + Rules::is('themes', 'popup_notification_theme-thirteen'), | |
| 660 | + ], 'or'), | |
| 589 | 661 | ], |
| 590 | 662 | [ |
| 591 | 663 | 'label' => __('Popup Icon', 'notificationx'), |
| 592 | 664 | 'name' => 'popup_icon', |
| @@ -611,10 +683,76 @@ | ||
| 611 | 683 | 'rules' => Rules::logicalRule([ |
| 612 | 684 | Rules::is('themes', 'popup_notification_theme-one'), |
| 613 | 685 | Rules::is('themes', 'popup_notification_theme-two'), |
| 614 | 686 | Rules::is('themes', 'popup_notification_theme-seven'), |
| 687 | + Rules::is('themes', 'popup_notification_theme-eight'), | |
| 688 | + Rules::is('themes', 'popup_notification_theme-eleven'), | |
| 689 | + Rules::is('themes', 'popup_notification_theme-twelve'), | |
| 690 | + Rules::is('themes', 'popup_notification_theme-thirteen'), | |
| 615 | 691 | ], 'or'), |
| 616 | 692 | ], |
| 693 | + // Coupon code (with copy-to-clipboard) for the coupon-popup card | |
| 694 | + // themes (theme-eight / -eleven / -twelve). | |
| 695 | + [ | |
| 696 | + 'label' => __('Coupon Code', 'notificationx'), | |
| 697 | + 'name' => 'popup_coupon_code', | |
| 698 | + 'type' => 'text', | |
| 699 | + 'priority' => 22, | |
| 700 | + // No global field-level default: it pre-filled the field with theme-eight's | |
| 701 | + // code and blocked theme-eleven/-twelve's own coupon-code defaults from | |
| 702 | + // applying on selection. Leave empty so the selected theme's default fills it. | |
| 703 | + 'default' => '', | |
| 704 | + 'placeholder' => __('GET35OFF', 'notificationx'), | |
| 705 | + 'rules' => Rules::logicalRule([ | |
| 706 | + Rules::is('themes', 'popup_notification_theme-eight'), | |
| 707 | + Rules::is('themes', 'popup_notification_theme-eleven'), | |
| 708 | + Rules::is('themes', 'popup_notification_theme-twelve'), | |
| 709 | + ], 'or'), | |
| 710 | + ], | |
| 711 | + // Multi-tier coupon "tickets" (percent + code + validity) for the | |
| 712 | + // multi-tier discount popup (theme-thirteen). | |
| 713 | + [ | |
| 714 | + 'label' => __('Coupon Tickets', 'notificationx'), | |
| 715 | + 'name' => 'popup_coupon_repeater', | |
| 716 | + 'type' => 'repeater', | |
| 717 | + 'priority' => 23, | |
| 718 | + 'rules' => Rules::is('themes', 'popup_notification_theme-thirteen'), | |
| 719 | + 'button' => [ | |
| 720 | + 'label' => __('Add Coupon', 'notificationx'), | |
| 721 | + ], | |
| 722 | + 'fields' => [ | |
| 723 | + [ | |
| 724 | + 'label' => __('Discount', 'notificationx'), | |
| 725 | + 'name' => 'coupon_percent', | |
| 726 | + 'type' => 'text', | |
| 727 | + 'placeholder' => __('e.g. 20%', 'notificationx'), | |
| 728 | + 'help' => __('Big discount value shown on the left (e.g. "20%").', 'notificationx'), | |
| 729 | + ], | |
| 730 | + [ | |
| 731 | + 'label' => __('Coupon Code', 'notificationx'), | |
| 732 | + 'name' => 'coupon_code', | |
| 733 | + 'type' => 'text', | |
| 734 | + 'placeholder' => __('e.g. #SAVE20', 'notificationx'), | |
| 735 | + ], | |
| 736 | + [ | |
| 737 | + 'label' => __('Validity', 'notificationx'), | |
| 738 | + 'name' => 'coupon_validity', | |
| 739 | + 'type' => 'text', | |
| 740 | + 'placeholder' => __('e.g. Valid for 7 Days', 'notificationx'), | |
| 741 | + ], | |
| 742 | + ], | |
| 743 | + // One starter coupon by default. The QuickBuilder repeater always | |
| 744 | + // renders a single row for an unsaved field, so a one-row default | |
| 745 | + // keeps the editor, the saved data and the front end consistent | |
| 746 | + // (all show one coupon); users add more with the Add Coupon button. | |
| 747 | + 'default' => [ | |
| 748 | + [ | |
| 749 | + 'coupon_percent' => __('20%', 'notificationx'), | |
| 750 | + 'coupon_code' => __('#SAVE20', 'notificationx'), | |
| 751 | + 'coupon_validity' => __('Valid for 7 Days', 'notificationx'), | |
| 752 | + ], | |
| 753 | + ], | |
| 754 | + ], | |
| 617 | 755 | // Form Field Toggles - only for form submission themes (4-7) |
| 618 | 756 | [ |
| 619 | 757 | 'label' => __('Show Name Field', 'notificationx'), |
| 620 | 758 | 'name' => 'popup_show_name_field', |
| @@ -705,9 +843,10 @@ | ||
| 705 | 843 | Rules::is('popup_show_message_field', true), |
| 706 | 844 | ]), |
| 707 | 845 | ], |
| 708 | 846 | |
| 709 | - // Common Button Text field for all themes | |
| 847 | + // Common Button Text field for all themes (theme-eleven and | |
| 848 | + // theme-twelve have no CTA — the copyable coupon code is the CTA). | |
| 710 | 849 | [ |
| 711 | 850 | 'label' => __('Button Text', 'notificationx'), |
| 712 | 851 | 'name' => 'popup_button_text', |
| 713 | 852 | 'type' => 'text', |
| @@ -712,8 +851,12 @@ | ||
| 712 | 851 | 'name' => 'popup_button_text', |
| 713 | 852 | 'type' => 'text', |
| 714 | 853 | 'priority' => 55, |
| 715 | 854 | 'default' => __('Get Offer', 'notificationx'), |
| 855 | + 'rules' => Rules::logicalRule([ | |
| 856 | + Rules::is('themes', 'popup_notification_theme-eleven', true), | |
| 857 | + Rules::is('themes', 'popup_notification_theme-twelve', true), | |
| 858 | + ], 'and'), | |
| 716 | 859 | ], |
| 717 | 860 | // Button URL field - only for themes 1-3 (promotional themes with external links) |
| 718 | 861 | [ |
| 719 | 862 | 'label' => __('Button URL', 'notificationx'), |
| @@ -724,8 +867,10 @@ | ||
| 724 | 867 | 'rules' => Rules::logicalRule([ |
| 725 | 868 | Rules::is('themes', 'popup_notification_theme-one'), |
| 726 | 869 | Rules::is('themes', 'popup_notification_theme-two'), |
| 727 | 870 | Rules::is('themes', 'popup_notification_theme-three'), |
| 871 | + Rules::is('themes', 'popup_notification_theme-eight'), | |
| 872 | + Rules::is('themes', 'popup_notification_theme-thirteen'), | |
| 728 | 873 | ], 'or'), |
| 729 | 874 | ], |
| 730 | 875 | |
| 731 | 876 | // Button Icon field - only for theme-three and theme-seven |
| @@ -768,8 +913,10 @@ | ||
| 768 | 913 | 'rules' => Rules::logicalRule([ |
| 769 | 914 | Rules::is('themes', 'popup_notification_theme-one'), |
| 770 | 915 | Rules::is('themes', 'popup_notification_theme-two'), |
| 771 | 916 | Rules::is('themes', 'popup_notification_theme-three'), |
| 917 | + Rules::is('themes', 'popup_notification_theme-eight'), | |
| 918 | + Rules::is('themes', 'popup_notification_theme-thirteen'), | |
| 772 | 919 | ], 'or'), |
| 773 | 920 | ], |
| 774 | 921 | // Repeater fields - only for theme-three |
| 775 | 922 | [ |
| @@ -826,8 +973,134 @@ | ||
| 826 | 973 | return $fields; |
| 827 | 974 | } |
| 828 | 975 | |
| 829 | 976 | /** |
| 977 | + * Fill EMPTY theme-specific fields from the selected theme's `defaults`. | |
| 978 | + * | |
| 979 | + * Why this is needed: the builder applies a theme's `defaults` on selection, but | |
| 980 | + * fields that are rules-gated OUT of the initial theme (e.g. popup_subtitle, | |
| 981 | + * popup_coupon_code, popup_coupon_repeater) get re-initialized to their own | |
| 982 | + * field-level default when they mount, clobbering the theme default. As a result | |
| 983 | + * the coupon themes (eleven/twelve/thirteen) ended up with the wrong/empty | |
| 984 | + * subtitle, coupon code and coupon tickets on a default (untouched) publish — so | |
| 985 | + * both the live Preview and the front end didn't match the design. | |
| 986 | + * | |
| 987 | + * This safety net fills only EMPTY values, so anything the user actually typed is | |
| 988 | + * preserved. A repeater row that holds only framework metadata (index/chosen/ | |
| 989 | + * selected) with no real content counts as empty. | |
| 990 | + * | |
| 991 | + * @param array $data Flat settings array (content fields at top level). | |
| 992 | + * @param string $theme_full Selected theme key, e.g. "popup_notification_theme-twelve". | |
| 993 | + * @return array | |
| 994 | + */ | |
| 995 | + private function fill_theme_defaults( $data, $theme_full ) { | |
| 996 | + if ( empty( $theme_full ) || empty( $this->themes ) || ! is_array( $data ) ) { | |
| 997 | + return $data; | |
| 998 | + } | |
| 999 | + // Strip the source-id prefix ("popup_notification_") to get the raw theme key. | |
| 1000 | + $prefix = $this->id . '_'; | |
| 1001 | + $theme_key = ( strpos( $theme_full, $prefix ) === 0 ) ? substr( $theme_full, strlen( $prefix ) ) : $theme_full; | |
| 1002 | + | |
| 1003 | + if ( empty( $this->themes[ $theme_key ]['defaults'] ) || ! is_array( $this->themes[ $theme_key ]['defaults'] ) ) { | |
| 1004 | + return $data; | |
| 1005 | + } | |
| 1006 | + // Keys the repeater/field framework injects into each row that carry no | |
| 1007 | + // user content — a row made up only of these is effectively empty. | |
| 1008 | + $meta_keys = array( 'index', 'chosen', 'selected' ); | |
| 1009 | + foreach ( $this->themes[ $theme_key ]['defaults'] as $key => $value ) { | |
| 1010 | + $current = isset( $data[ $key ] ) ? $data[ $key ] : null; | |
| 1011 | + $is_empty = ( null === $current || '' === $current ); | |
| 1012 | + if ( is_array( $current ) ) { | |
| 1013 | + // Empty array, or an array whose rows only hold framework metadata | |
| 1014 | + // (e.g. a clobbered repeater like [{index, chosen, selected}]). | |
| 1015 | + $has_real = false; | |
| 1016 | + foreach ( $current as $item ) { | |
| 1017 | + if ( is_array( $item ) ) { | |
| 1018 | + foreach ( $item as $ik => $iv ) { | |
| 1019 | + if ( ! in_array( $ik, $meta_keys, true ) && '' !== $iv && null !== $iv ) { | |
| 1020 | + $has_real = true; | |
| 1021 | + break 2; | |
| 1022 | + } | |
| 1023 | + } | |
| 1024 | + } elseif ( '' !== $item && null !== $item ) { | |
| 1025 | + $has_real = true; | |
| 1026 | + break; | |
| 1027 | + } | |
| 1028 | + } | |
| 1029 | + $is_empty = ! $has_real; | |
| 1030 | + } | |
| 1031 | + if ( $is_empty ) { | |
| 1032 | + $data[ $key ] = $value; | |
| 1033 | + } | |
| 1034 | + } | |
| 1035 | + return $data; | |
| 1036 | + } | |
| 1037 | + | |
| 1038 | + /** | |
| 1039 | + * Apply theme defaults to empty fields at save time (persisted + front end). | |
| 1040 | + * Hooked automatically via nx_save_post_{$this->id} (see Extension::init()). | |
| 1041 | + * | |
| 1042 | + * @param array $post Post row about to be persisted; settings live in $post['data']. | |
| 1043 | + * @param array $data Full submitted settings. | |
| 1044 | + * @param int $nx_id Notification id (0 on create). | |
| 1045 | + * @return array | |
| 1046 | + */ | |
| 1047 | + public function save_post( $post, $data, $nx_id ) { | |
| 1048 | + if ( isset( $post['data'] ) && is_array( $post['data'] ) ) { | |
| 1049 | + $theme_full = ! empty( $data['themes'] ) ? $data['themes'] : ( ! empty( $post['theme'] ) ? $post['theme'] : '' ); | |
| 1050 | + $post['data'] = $this->fill_theme_defaults( $post['data'], $theme_full ); | |
| 1051 | + $post['data'] = $this->strip_empty_repeater_rows( $post['data'] ); | |
| 1052 | + } | |
| 1053 | + return $post; | |
| 1054 | + } | |
| 1055 | + | |
| 1056 | + /** | |
| 1057 | + * Drop repeater rows that hold only framework metadata (index/chosen/selected) | |
| 1058 | + * and no real content. The QuickBuilder repeater commits a freshly "Add"ed row | |
| 1059 | + * with just an "index" until its inputs are edited, so an untouched extra coupon | |
| 1060 | + * would otherwise persist as an empty ticket that renders as a broken blank | |
| 1061 | + * ticket on the front end. Only the known coupon repeater is cleaned, so no other | |
| 1062 | + * data is affected. | |
| 1063 | + * | |
| 1064 | + * @param array $data Flat settings array. | |
| 1065 | + * @return array | |
| 1066 | + */ | |
| 1067 | + private function strip_empty_repeater_rows( $data ) { | |
| 1068 | + $meta_keys = array( 'index', 'chosen', 'selected' ); | |
| 1069 | + $repeater_fields = array( 'popup_coupon_repeater' ); | |
| 1070 | + foreach ( $repeater_fields as $field ) { | |
| 1071 | + if ( empty( $data[ $field ] ) || ! is_array( $data[ $field ] ) ) { | |
| 1072 | + continue; | |
| 1073 | + } | |
| 1074 | + $data[ $field ] = array_values( array_filter( $data[ $field ], function ( $row ) use ( $meta_keys ) { | |
| 1075 | + if ( ! is_array( $row ) ) { | |
| 1076 | + return '' !== $row && null !== $row; | |
| 1077 | + } | |
| 1078 | + foreach ( $row as $k => $v ) { | |
| 1079 | + if ( ! in_array( $k, $meta_keys, true ) && '' !== $v && null !== $v ) { | |
| 1080 | + return true; | |
| 1081 | + } | |
| 1082 | + } | |
| 1083 | + return false; | |
| 1084 | + } ) ); | |
| 1085 | + } | |
| 1086 | + return $data; | |
| 1087 | + } | |
| 1088 | + | |
| 1089 | + /** | |
| 1090 | + * Apply theme defaults to empty fields for the live builder Preview, so the | |
| 1091 | + * preview matches the design even before anything is saved. | |
| 1092 | + * Hooked automatically via nx_preview_settings_{$this->id} (see Extension::init()). | |
| 1093 | + * | |
| 1094 | + * @param array $settings Flat preview settings. | |
| 1095 | + * @return array | |
| 1096 | + */ | |
| 1097 | + public function preview_settings( $settings ) { | |
| 1098 | + $theme_full = ! empty( $settings['themes'] ) ? $settings['themes'] : ( ! empty( $settings['theme'] ) ? $settings['theme'] : '' ); | |
| 1099 | + return $this->fill_theme_defaults( $settings, $theme_full ); | |
| 1100 | + } | |
| 1101 | + | |
| 1102 | + /** | |
| 830 | 1103 | * Generate entry key |
| 831 | 1104 | * |
| 832 | 1105 | * @param string $key |
| 833 | 1106 | * @return string |
| @@ -910,13 +1183,13 @@ | ||
| 910 | 1183 | * @return string |
| 911 | 1184 | */ |
| 912 | 1185 | private function get_user_ip() { |
| 913 | 1186 | if (!empty($_SERVER['HTTP_CLIENT_IP'])) { |
| 914 | - return $_SERVER['HTTP_CLIENT_IP']; | |
| 1187 | + return sanitize_text_field(wp_unslash($_SERVER['HTTP_CLIENT_IP'])); | |
| 915 | 1188 | } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { |
| 916 | - return $_SERVER['HTTP_X_FORWARDED_FOR']; | |
| 1189 | + return sanitize_text_field(wp_unslash($_SERVER['HTTP_X_FORWARDED_FOR'])); | |
| 917 | 1190 | } else { |
| 918 | - return $_SERVER['REMOTE_ADDR'] ?? ''; | |
| 1191 | + return isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : ''; | |
| 919 | 1192 | } |
| 920 | 1193 | } |
| 921 | 1194 | |
| 922 | 1195 | |
| @@ -947,8 +1220,63 @@ | ||
| 947 | 1220 | 'label' => __('Center', 'notificationx'), |
| 948 | 1221 | 'value' => 'center', |
| 949 | 1222 | 'rules' => Rules::is('source', $this->id), |
| 950 | 1223 | ]; |
| 1224 | + // Exit Intent Popup conversion (Announcement type). | |
| 1225 | + $fields['exit_intent_settings'] = [ | |
| 1226 | + 'label' => __('Exit Intent Popup', 'notificationx'), | |
| 1227 | + 'name' => 'exit_intent_settings', | |
| 1228 | + 'type' => 'section', | |
| 1229 | + 'priority' => 14, | |
| 1230 | + 'rules' => Rules::_is('source', $this->id), | |
| 1231 | + 'fields' => [ | |
| 1232 | + 'convert_to_exit_intent' => [ | |
| 1233 | + 'label' => __('Convert to Exit Intent Popup', 'notificationx'), | |
| 1234 | + 'name' => 'convert_to_exit_intent', | |
| 1235 | + 'type' => 'checkbox', | |
| 1236 | + 'default' => false, | |
| 1237 | + 'priority' => 5, | |
| 1238 | + 'description' => __('Show this Announcement as a centered popup when the visitor is about to leave the page.', 'notificationx'), | |
| 1239 | + ], | |
| 1240 | + 'exit_intent_cookie_duration' => [ | |
| 1241 | + 'label' => __('Cookie Duration', 'notificationx'), | |
| 1242 | + 'name' => 'exit_intent_cookie_duration', | |
| 1243 | + 'type' => 'number', | |
| 1244 | + 'default' => 7, | |
| 1245 | + 'min' => 1, | |
| 1246 | + 'max' => 365, | |
| 1247 | + 'priority' => 10, | |
| 1248 | + 'description' => __('Days', 'notificationx'), | |
| 1249 | + 'help' => __('Suppress the popup for this many days after it has been shown to a visitor.', 'notificationx'), | |
| 1250 | + 'rules' => Rules::_is('convert_to_exit_intent', true), | |
| 1251 | + ], | |
| 1252 | + ], | |
| 1253 | + ]; | |
| 1254 | + | |
| 1255 | + $hide_when_exit_intent = Rules::logicalRule([ | |
| 1256 | + Rules::_is('source', $this->id, true), | |
| 1257 | + Rules::_is('convert_to_exit_intent', true, true), | |
| 1258 | + ], 'or'); | |
| 1259 | + | |
| 1260 | + if (isset($fields['timing']['fields']['display_for'])) { | |
| 1261 | + $fields['timing']['fields']['display_for'] = Rules::add( | |
| 1262 | + $hide_when_exit_intent, | |
| 1263 | + $fields['timing']['fields']['display_for'] | |
| 1264 | + ); | |
| 1265 | + } | |
| 1266 | + if (isset($fields['timing']['fields']['delay_between'])) { | |
| 1267 | + $fields['timing']['fields']['delay_between'] = Rules::add( | |
| 1268 | + $hide_when_exit_intent, | |
| 1269 | + $fields['timing']['fields']['delay_between'] | |
| 1270 | + ); | |
| 1271 | + } | |
| 1272 | + if (isset($_fields['position'])) { | |
| 1273 | + $_fields['position'] = Rules::add( | |
| 1274 | + $hide_when_exit_intent, | |
| 1275 | + $_fields['position'] | |
| 1276 | + ); | |
| 1277 | + } | |
| 1278 | + | |
| 951 | 1279 | // Popup specific settings |
| 952 | 1280 | $fields['popup_settings'] = [ |
| 953 | 1281 | 'label' => __('Popup Settings', 'notificationx'), |
| 954 | 1282 | 'name' => 'popup_settings', |
| @@ -987,8 +1315,9 @@ | ||
| 987 | 1315 | return $fields; |
| 988 | 1316 | } |
| 989 | 1317 | |
| 990 | 1318 | public function doc(){ |
| 1319 | + /* translators: %1$s: step-by-step guides link URL, %2$s: tutorial link URL, %3$s: URL */ | |
| 991 | 1320 | return sprintf(__('<p>Create compelling Announcements that capture visitor interest and help you generate more leads on your WordPress site. Need help? Check out our <a href="%1$s" target="_blank">step-by-step guides</a> to build impactful Announcements.</p> |
| 992 | 1321 | <p>🎦 Watch the quick video <a target="_blank" href="%2$s">tutorial</a> for an easy walk-through.</p> |
| 993 | 1322 | <p><strong>Recommended Blogs:</strong></p> |
| 994 | 1323 | <p>🔥 <a target="_blank" href="%3$s">How to Create High-Performing Announcements with NotificationX?</a></p> |