PluginProbe ʕ •ᴥ•ʔ
ShopEngine Elementor WooCommerce Builder Addon – All in One WooCommerce Solution with eCommerce Templates & Woo Widgets / 4.9.4
ShopEngine Elementor WooCommerce Builder Addon – All in One WooCommerce Solution with eCommerce Templates & Woo Widgets v4.9.4
4.9.5 4.9.4 4.9.3 4.9.2 4.9.1 4.9.0 2.0.0 2.1.0 2.2.0 2.2.1 2.2.2 2.3.0 2.4.0 2.5.0 2.5.1 3.0.0 3.1.0 3.1.1 4.0.0 4.0.1 4.1.0 4.1.1 4.2.0 4.2.1 4.3.0 4.3.1 4.4.0 4.5.0 4.5.1 4.6.0 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.6.6 4.6.7 4.6.8 4.6.9 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.7.5 4.7.6 4.7.7 4.7.8 4.7.9 4.8.0 4.8.1 4.8.2 4.8.3 4.8.4 4.8.5 4.8.6 4.8.7 4.8.8 4.8.9 trunk 0.1.2-beta 0.1.3-beta 0.1.4-beta 1.0.0 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.2.1 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.5.0 1.5.1 1.6.0 1.6.1 1.7.0 1.8.0 1.8.1 1.9.0
shopengine / utils / onboard / auto-install-notice.php
shopengine / utils / onboard Last commit date
auto-install-notice.php 2 weeks ago auto-install-tracker.php 2 weeks ago plugin-installer.php 2 weeks ago plugin-skin.php 1 year ago
auto-install-notice.php
284 lines
1 <?php
2
3 namespace ShopEngine\Utils\Onboard;
4
5 defined( 'ABSPATH' ) || exit;
6
7 class Auto_Install_Notice {
8
9 const DISMISSED_KEY = 'shopengine_auto_install_notice_dismissed';
10 const EMAIL_COLLECTED_KEY = 'wpmet_onboard_email_collected';
11
12 public static function init(): void {
13 add_action( 'admin_footer', [ __CLASS__, 'render' ] );
14 add_action( 'wp_ajax_shopengine_dismiss_auto_install_notice', [ __CLASS__, 'handle_dismiss' ] );
15 add_action( 'wp_ajax_shopengine_confirm_auto_install_notice', [ __CLASS__, 'handle_confirm' ] );
16 }
17
18 public static function render(): void {
19 if ( ! current_user_can( 'manage_options' ) ) {
20 return;
21 }
22
23 if ( get_option( self::DISMISSED_KEY ) ) {
24 return;
25 }
26
27 if ( \ShopEngine\Utils\Util::get_settings( 'shopengine_user_consent_for_banner', 'true' ) !== 'true' ) {
28 return;
29 }
30
31 // Only show when ShopEngine was auto-installed by another wpmet plugin.
32 $registry = Auto_Install_Tracker::get_registry();
33 $auto_installed = isset( $registry['shopengine/shopengine.php'] );
34
35 if ( ! $auto_installed ) {
36 return;
37 }
38
39 // Only show on ShopEngine's own admin pages.
40 $screen = get_current_screen();
41 if ( ! $screen || strpos( $screen->id, 'shopengine' ) === false ) {
42 return;
43 }
44
45 $nonce = wp_create_nonce( 'shopengine_auto_install_notice_nonce' );
46 $ajax_url = esc_js( admin_url( 'admin-ajax.php' ) );
47 $heading = esc_js( __( 'Get more from your new plugins 🚀', 'shopengine' ) );
48 $desc = esc_js( __( 'Allow us to use non-sensitive data from your site to improve our products and get personalized performance tips.', 'shopengine' ) );
49 $skip_label = esc_js( __( 'Skip for Now', 'shopengine' ) );
50 $confirm_label = esc_js( __( 'Confirm & Apply', 'shopengine' ) );
51 $applying = esc_js( __( 'Applying…', 'shopengine' ) );
52 ?>
53 <style>
54 @property --angle {
55 syntax: '<angle>';
56 initial-value: 162.14deg;
57 inherits: false;
58 }
59 #wpmet-shopengine-notice-skip,
60 #wpmet-shopengine-notice-confirm {
61 display: flex;
62 align-items: center;
63 justify-content: center;
64 min-height: unset;
65 line-height: unset;
66 box-sizing: border-box;
67 padding: 9px 20px;
68 border-radius: 8px;
69 flex: none;
70 font-size: 13px;
71 white-space: nowrap;
72 cursor: pointer;
73 }
74 #wpmet-shopengine-notice-skip {
75 background: #fff;
76 border: 1px solid #d7d7db;
77 color: #000;
78 transition: background 250ms ease, border-color 250ms ease, color 250ms ease;
79 }
80 #wpmet-shopengine-notice-skip:hover {
81 background: #dbeafe;
82 border: 1px solid #dbeafe;
83 color: #000;
84 }
85 #wpmet-shopengine-notice-confirm {
86 position: relative;
87 overflow: hidden;
88 isolation: isolate;
89 --angle: 162.14deg;
90 background: linear-gradient(var(--angle), #4371F8 7.19%, #2B58DE 44.76%);
91 border: none;
92 color: #fff;
93 }
94 #wpmet-shopengine-notice-confirm::after {
95 content: "";
96 position: absolute;
97 top: -60%;
98 right: -10%;
99 width: 65%;
100 height: 200%;
101 background: rgba(255, 255, 255, 0.10);
102 border-radius: 60% 0 0 10%;
103 transform: rotate(20deg);
104 transform-origin: bottom left;
105 z-index: -1;
106 pointer-events: none;
107 transition: top 300ms ease, right 300ms ease, opacity 300ms ease;
108 }
109 #wpmet-shopengine-notice-confirm:hover::after {
110 top: -70%;
111 right: 0%;
112 opacity: 0.7;
113 }
114 .ant-notification {
115 z-index: 9999999 !important;
116 }
117 </style>
118 <script>
119 (function() {
120 var NONCE = '<?php echo esc_js( $nonce ); ?>';
121 var AJAXURL = '<?php echo $ajax_url; ?>';
122 var dismissed = false;
123
124 function setContentPadding( height ) {
125 var el = document.getElementById( 'wpcontent' );
126 if ( el ) { el.style.setProperty( 'padding-top', height + 'px', 'important' ); }
127 }
128
129 function clearContentPadding() {
130 var el = document.getElementById( 'wpcontent' );
131 if ( el ) { el.style.removeProperty( 'padding-top' ); }
132 }
133
134 function removeNotice() {
135 dismissed = true;
136 clearContentPadding();
137 var el = document.querySelector( '.wpmet-shopengine-auto-install-notice' );
138 if ( el ) {
139 el.style.opacity = '0';
140 el.style.transition = 'opacity 0.3s';
141 setTimeout( function() { if ( el.parentNode ) { el.parentNode.removeChild( el ); } }, 320 );
142 }
143 }
144
145 function doPost( action, cb ) {
146 var xhr = new XMLHttpRequest();
147 xhr.open( 'POST', AJAXURL );
148 xhr.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
149 xhr.onload = function() { if ( cb ) { cb(); } };
150 xhr.send( 'action=' + encodeURIComponent( action ) + '&nonce=' + encodeURIComponent( NONCE ) );
151 }
152
153 function isBlockedPage() {
154 var h = window.location.hash;
155 var s = window.location.search;
156 return h === '#shopengine-modules' || h === '#shopengine-widgets' || h === '#getting-started'
157 || s.indexOf( 'page=shopengine_wpmet_plugins' ) !== -1;
158 }
159
160 function injectNotice() {
161 if ( dismissed ) { return; }
162 if ( isBlockedPage() ) { return; }
163 if ( document.querySelector( '.wpmet-shopengine-auto-install-notice' ) ) { return; }
164
165 var div = document.createElement( 'div' );
166 div.className = 'wpmet-shopengine-auto-install-notice';
167 div.style.cssText = [
168 'display:flex', 'align-items:center', 'justify-content:space-between',
169 'gap:20px', 'min-height:104px', 'box-sizing:border-box',
170 'position:fixed', 'top:32px', 'left:160px', 'right:0',
171 'z-index:999999', 'padding:16px 20px',
172 'background:#fff', 'border-left:4px solid #E91E8C',
173 'box-shadow:0 2px 8px rgba(0,0,0,.15)'
174 ].join( ';' );
175
176 div.innerHTML =
177 '<div style="flex:1 1 auto;">' +
178 '<h3 style="margin:0 0 6px;font-family:Inter,sans-serif;font-size:24px;font-weight:700;line-height:24px;letter-spacing:0;"><?php echo $heading; ?></h3>' +
179 '<p style="margin:0;color:#50575E;font-family:Inter,sans-serif;font-weight:500;font-size:16px;line-height:24px;letter-spacing:0;"><?php echo $desc; ?></p>' +
180 '</div>' +
181 '<div style="flex:0 0 auto;display:flex;gap:10px;">' +
182 '<button class="button" id="wpmet-shopengine-notice-skip"><?php echo $skip_label; ?></button>' +
183 '<button class="button button-primary" id="wpmet-shopengine-notice-confirm"><?php echo $confirm_label; ?></button>' +
184 '</div>';
185
186 document.body.appendChild( div );
187
188 var noticeHeight = div.offsetHeight || 104;
189 setContentPadding( noticeHeight );
190
191 document.getElementById( 'wpmet-shopengine-notice-skip' ).addEventListener( 'click', function() {
192 doPost( 'shopengine_dismiss_auto_install_notice' );
193 removeNotice();
194 } );
195
196 document.getElementById( 'wpmet-shopengine-notice-confirm' ).addEventListener( 'click', function() {
197 var btn = this;
198 btn.disabled = true;
199 btn.textContent = '<?php echo $applying; ?>';
200 doPost( 'shopengine_confirm_auto_install_notice', function() {
201 removeNotice();
202 } );
203 } );
204 }
205
206 function tryInject() {
207 setTimeout( injectNotice, 300 );
208 }
209
210 if ( document.readyState === 'loading' ) {
211 document.addEventListener( 'DOMContentLoaded', tryInject );
212 } else {
213 tryInject();
214 }
215
216 window.addEventListener( 'hashchange', function() {
217 if ( dismissed ) { return; }
218 var existing = document.querySelector( '.wpmet-shopengine-auto-install-notice' );
219 if ( existing && existing.parentNode ) { existing.parentNode.removeChild( existing ); }
220 clearContentPadding();
221 setTimeout( injectNotice, 400 );
222 } );
223
224 document.addEventListener( 'visibilitychange', function() {
225 if ( document.visibilityState === 'visible' ) { tryInject(); }
226 } );
227
228 window.addEventListener( 'pageshow', function( e ) {
229 if ( e.persisted ) { tryInject(); }
230 } );
231 })();
232 </script>
233 <?php
234 }
235
236 public static function handle_dismiss(): void {
237 check_ajax_referer( 'shopengine_auto_install_notice_nonce', 'nonce' );
238 if ( ! current_user_can( 'manage_options' ) ) {
239 wp_send_json_error();
240 }
241 update_option( self::DISMISSED_KEY, true, false );
242 wp_send_json_success();
243 }
244
245 public static function handle_confirm(): void {
246 check_ajax_referer( 'shopengine_auto_install_notice_nonce', 'nonce' );
247 if ( ! current_user_can( 'manage_options' ) ) {
248 wp_send_json_error();
249 }
250
251 $stored_email = get_option( 'wpmet_onboard_collected_email' );
252 $email = $stored_email
253 ? sanitize_email( $stored_email )
254 : sanitize_email( get_option( 'admin_email' ) );
255
256 \ShopEngine\Core\Onboard\Plugin_Data_Sender::instance()->sendEmailSubscribeData( 'plugin-subscribe', [
257 'email' => $email,
258 'slug' => 'shopengine',
259 ] );
260
261 // Also send for auto-installed plugins that don't have their own notice banner.
262 $registry = Auto_Install_Tracker::get_registry();
263 $slug_map = [
264 'elementskit-lite/elementskit-lite.php' => 'elementskit-lite',
265 'emailkit/EmailKit.php' => 'emailkit',
266 'gutenkit-blocks-addon/gutenkit-blocks-addon.php' => 'gutenkit-blocks-addon',
267 'getgenie/getgenie.php' => 'getgenie',
268 'popup-builder-block/popup-builder-block.php' => 'popupkit',
269 ];
270 foreach ( array_keys( $registry ) as $plugin_file ) {
271 if ( isset( $slug_map[ $plugin_file ] ) ) {
272 \ShopEngine\Core\Onboard\Plugin_Data_Sender::instance()->sendEmailSubscribeData( 'plugin-subscribe', [
273 'email' => $email,
274 'slug' => $slug_map[ $plugin_file ],
275 ] );
276 }
277 }
278
279 update_option( self::EMAIL_COLLECTED_KEY, true, false );
280 update_option( self::DISMISSED_KEY, true, false );
281 wp_send_json_success();
282 }
283 }
284