PluginProbe ʕ •ᴥ•ʔ
EmbedPress – PDF Embedder, Embed PDF viewer, YouTube Videos, 3D FlipBook, Social feeds & more / 3.3.3
EmbedPress – PDF Embedder, Embed PDF viewer, YouTube Videos, 3D FlipBook, Social feeds & more v3.3.3
4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 trunk 1.0.0 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 2.0.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2.0 2.2.1 2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.1.3 3.2.0 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.7.0 3.7.1 3.7.2 3.7.3 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9 4.0.0 4.0.1 4.0.10 4.0.11 4.0.12 4.0.13 4.0.14 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.0.9 4.1.0 4.1.1 4.1.10 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.8 4.2.9 4.3.0 4.3.1 4.4.0 4.4.1 4.4.10 4.4.11 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 4.5.0 4.5.1
embedpress / EmbedPress / Includes / Classes / EmbedPress_Plugin_Usage_Tracker.php
embedpress / EmbedPress / Includes / Classes Last commit date
Elementor_Enhancer.php 4 years ago EmbedPress_Core_Installer.php 6 years ago EmbedPress_Notice.php 4 years ago EmbedPress_Plugin_Usage_Tracker.php 4 years ago Feature_Enhancer.php 4 years ago Helper.php 4 years ago
EmbedPress_Plugin_Usage_Tracker.php
908 lines
1 <?php
2 /**
3 * EmbedPress_Plugin_Usage_Tracker
4 * This class is responsible for data sending to insights.
5 * @version 3.0.0
6 */
7 namespace EmbedPress\Includes\Classes;
8 /**
9 * Exit if accessed directly
10 */
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14 /**
15 * Main SDK for EmbedPress_Plugin_Usage_Tracker.
16 */
17 if( ! class_exists('EmbedPress_Plugin_Usage_Tracker') ) :
18 class EmbedPress_Plugin_Usage_Tracker {
19 /**
20 * WP Insights Version
21 */
22 const WPINS_VERSION = '3.0.2';
23 /**
24 * API URL
25 */
26 const API_URL = 'https://send.wpinsight.com/process-plugin-data';
27 /**
28 * Installed Plugin File
29 *
30 * @var string
31 */
32 private $plugin_file = null;
33 /**
34 * Installed Plugin Name
35 *
36 * @var string
37 */
38 private $plugin_name = null;
39 /**
40 * How often the event should subsequently
41 * @var string
42 */
43 public $recurrence = 'daily';
44 private $event_hook = null;
45 /**
46 * Instace of EmbedPress_Plugin_Usage_Tracker
47 * @var EmbedPress_Plugin_Usage_Tracker
48 */
49 private static $_instance = null;
50 /**
51 * Get Instance of EmbedPress_Plugin_Usage_Tracker
52 * @return EmbedPress_Plugin_Usage_Tracker
53 */
54 public static function get_instance( $plugin_file, $args = [] ){
55 if( is_null( static::$_instance ) ) {
56 static::$_instance = new static( $plugin_file, $args );
57 }
58 return static::$_instance;
59 }
60 /**
61 * Automatically Invoked when initialized.
62 *
63 * @param array $args
64 */
65 public function __construct( $plugin_file, $args = [] ){
66 $this->plugin_file = $plugin_file;
67 $this->plugin_name = basename( $this->plugin_file, '.php' );
68 $this->disabled_wp_cron = defined('DISABLE_WP_CRON') && DISABLE_WP_CRON == true;
69 $this->enable_self_cron = $this->disabled_wp_cron == true ? true : false;
70
71 $this->event_hook = 'put_do_weekly_action';
72
73 $this->require_optin = isset( $args['opt_in'] ) ? $args['opt_in'] : true;
74 $this->include_goodbye_form = isset( $args['goodbye_form'] ) ? $args['goodbye_form'] : true;
75 $this->marketing = isset( $args['email_marketing'] ) ? $args['email_marketing'] : true;
76 $this->options = isset( $args['options'] ) ? $args['options'] : [];
77 $this->item_id = isset( $args['item_id'] ) ? $args['item_id'] : false;
78 /**
79 * Activation Hook
80 */
81 register_activation_hook( $this->plugin_file, array( $this, 'activate_this_plugin' ) );
82 /**
83 * Deactivation Hook
84 */
85 register_deactivation_hook( $this->plugin_file, array( $this, 'deactivate_this_plugin' ) );
86 }
87 /**
88 * When user agreed to opt-in tracking schedule is enabled.
89 * @since 3.0.0
90 */
91 public function schedule_tracking() {
92 if( $this->disabled_wp_cron ) {
93 return;
94 }
95 if ( ! wp_next_scheduled( $this->event_hook ) ) {
96 wp_schedule_event( time(), $this->recurrence, $this->event_hook );
97 }
98 }
99 /**
100 * Add the schedule event if the plugin is tracked.
101 *
102 * @return void
103 */
104 public function activate_this_plugin(){
105 $allow_tracking = $this->is_tracking_allowed();
106 if( ! $allow_tracking ) {
107 return;
108 }
109 $this->schedule_tracking();
110 }
111 /**
112 * Remove the schedule event when plugin is deactivated and send the deactivated reason to inishghts if user submitted.
113 * @since 3.0.0
114 */
115 public function deactivate_this_plugin() {
116 /**
117 * Check tracking is allowed or not.
118 */
119 $allow_tracking = $this->is_tracking_allowed();
120 if( ! $allow_tracking ) {
121 return;
122 }
123 $body = $this->get_data();
124 $body['status'] = 'Deactivated';
125 $body['deactivated_date'] = time();
126
127 // Check deactivation reason and add for insights data.
128 if( false !== get_option( 'wpins_deactivation_reason_' . $this->plugin_name ) ) {
129 $body['deactivation_reason'] = get_option( 'wpins_deactivation_reason_' . $this->plugin_name );
130 }
131 if( false !== get_option( 'wpins_deactivation_details_' . $this->plugin_name ) ) {
132 $body['deactivation_details'] = get_option( 'wpins_deactivation_details_' . $this->plugin_name );
133 }
134
135 $this->send_data( $body );
136 delete_option( 'wpins_deactivation_reason_' . $this->plugin_name );
137 delete_option( 'wpins_deactivation_details_' . $this->plugin_name );
138 /**
139 * Clear the event schedule.
140 */
141 if( ! $this->disabled_wp_cron ) {
142 wp_clear_scheduled_hook( $this->event_hook );
143 }
144 }
145 /**
146 * Initial Method to Hook Everything.
147 * @return void
148 */
149 public function init(){
150 add_action( 'wpdeveloper_notice_clicked_for_' . $this->plugin_name, array( $this, 'clicked' ) );
151 add_action( $this->event_hook, array( $this, 'do_tracking' ) );
152 // For Test
153 // add_action( 'admin_init', array( $this, 'force_tracking' ) );
154 add_action( 'wpdeveloper_optin_notice_for_' . $this->plugin_name, array( $this, 'notice' ) );
155 /**
156 * Deactivation Reason Form and Submit Data to Insights.
157 */
158 add_filter( 'plugin_action_links_' . plugin_basename( $this->plugin_file ), array( $this, 'deactivate_action_links' ) );
159 add_action( 'admin_footer-plugins.php', array( $this, 'deactivate_reasons_form' ) );
160 add_action( 'wp_ajax_deactivation_form_' . esc_attr( $this->plugin_name ), array( $this, 'deactivate_reasons_form_submit' ) );
161 }
162 /**
163 * For Redirecting Current Page without Arguments!
164 *
165 * @return void
166 */
167 private function redirect_to(){
168 $request_uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
169 $query_string = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_QUERY );
170 parse_str( $query_string, $current_url );
171
172 $unset_array = array( 'dismiss', 'plugin', '_wpnonce', 'later', 'plugin_action', 'marketing_optin' );
173
174 foreach( $unset_array as $value ) {
175 if( isset( $current_url[ $value ] ) ) {
176 unset( $current_url[ $value ] );
177 }
178 }
179
180 $current_url = http_build_query($current_url);
181 $redirect_url = $request_uri . '?' . $current_url;
182 return $redirect_url;
183 }
184 /**
185 * This method forcing the do_tracking method to execute instant.
186 * @return void
187 */
188 public function force_tracking(){
189 $this->do_tracking( true );
190 }
191 /**
192 * This method is responsible for all the magic from the front of the plugin.
193 * @since 3.0.0
194 * @param $force Force tracking if it's not the correct time to track/
195 */
196 public function do_tracking( $force = false ) {
197 /**
198 * Check URL is set or not.
199 */
200 if ( empty( self::API_URL ) ) {
201 return;
202 }
203 /**
204 * Check is tracking allowed or not.
205 */
206 if( ! $this->is_tracking_allowed() ) {
207 return;
208 }
209 /**
210 * Check is this the correct time to track or not.
211 * or Force to track.
212 */
213 if( ! $this->is_time_to_track() && ! $force ) {
214 return;
215 }
216 /**
217 * Get All Data.
218 */
219 $body = $this->get_data();
220 /**
221 * Send all data.
222 */
223 return $this->send_data( $body );
224 }
225 /**
226 * Is tracking allowed?
227 * @since 1.0.0
228 */
229 private function is_tracking_allowed() {
230 // First, check if the user has changed their mind and opted out of tracking
231 if( $this->has_user_opted_out() ) {
232 $this->set_is_tracking_allowed( false, $this->plugin_name );
233 return false;
234 }
235 // The wpins_allow_tracking option is an array of plugins that are being tracked
236 $allow_tracking = get_option( 'wpins_allow_tracking' );
237 // If this plugin is in the array, then tracking is allowed
238 if( isset( $allow_tracking[$this->plugin_name] ) ) {
239 return true;
240 }
241 return false;
242 }
243 /**
244 * Set a flag in DB If tracking is allowed.
245 *
246 * @since 3.0.0
247 * @param $is_allowed Boolean true if is allowed.
248 */
249 protected function set_is_tracking_allowed( $is_allowed, $plugin = null ) {
250 if( empty( $plugin ) ) {
251 $plugin = $this->plugin_name;
252 }
253 /**
254 * Get All Tracked Plugin List using this Tracker.
255 */
256 $allow_tracking = get_option( 'wpins_allow_tracking' );
257 /**
258 * Check user is opted out for tracking or not.
259 */
260 if( $this->has_user_opted_out() ) {
261 if( isset( $allow_tracking[$plugin] ) ) {
262 unset( $allow_tracking[$plugin] );
263 }
264 } else if( $is_allowed || ! $this->require_optin ) {
265 /**
266 * If user has agreed to allow tracking
267 */
268 if( empty( $allow_tracking ) || ! is_array( $allow_tracking ) ) {
269 $allow_tracking = array( $plugin => $plugin );
270 } else {
271 $allow_tracking[$plugin] = $plugin;
272 }
273 } else {
274 if( isset( $allow_tracking[$plugin] ) ) {
275 unset( $allow_tracking[$plugin] );
276 }
277 }
278 update_option( 'wpins_allow_tracking', $allow_tracking );
279 }
280
281 /**
282 * Check the user has opted out or not.
283 *
284 * @since 3.0.0
285 * @return Boolean
286 */
287 protected function has_user_opted_out() {
288 if( ! empty( $this->options ) ) {
289 foreach( $this->options as $option_name ) {
290 $options = get_option( $option_name );
291 if( ! empty( $options['wpins_opt_out'] ) ) {
292 return true;
293 }
294 }
295 }
296 return false;
297 }
298 /**
299 * Check if it's time to track
300 *
301 * @since 3.0.0
302 */
303 public function is_time_to_track() {
304 $track_times = get_option( 'wpins_last_track_time', array() );
305 return ! isset( $track_times[$this->plugin_name] ) ? true :
306 ( ( isset( $track_times[$this->plugin_name] ) && $track_times[$this->plugin_name] ) < strtotime( '-1 day' ) ? true : false );
307 }
308 /**
309 * Set tracking time.
310 *
311 * @since 3.0.0
312 */
313 public function set_track_time() {
314 $track_times = get_option( 'wpins_last_track_time', array() );
315 $track_times[ $this->plugin_name ] = time();
316 update_option( 'wpins_last_track_time', $track_times );
317 }
318 /**
319 * This method is responsible for collecting all data.
320 *
321 * @since 3.0.0
322 */
323 public function get_data() {
324 $body = array(
325 'plugin_slug' => sanitize_text_field( $this->plugin_name ),
326 'url' => get_bloginfo( 'url' ),
327 'site_name' => get_bloginfo( 'name' ),
328 'site_version' => get_bloginfo( 'version' ),
329 'site_language' => get_bloginfo( 'language' ),
330 'charset' => get_bloginfo( 'charset' ),
331 'wpins_version' => self::WPINS_VERSION,
332 'php_version' => phpversion(),
333 'multisite' => is_multisite(),
334 'file_location' => __FILE__
335 );
336
337 // Collect the email if the correct option has been set
338 if( $this->marketing ) {
339 if( ! function_exists( 'wp_get_current_user' ) ) {
340 include ABSPATH . 'wp-includes/pluggable.php';
341 }
342 $current_user = wp_get_current_user();
343 $email = $current_user->user_email;
344 if( is_email( $email ) ) {
345 $body['email'] = $email;
346 }
347 }
348 $body['marketing_method'] = $this->marketing;
349 $body['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : '';
350
351 /**
352 * Collect all active and inactive plugins
353 */
354 if( ! function_exists( 'get_plugins' ) ) {
355 include ABSPATH . '/wp-admin/includes/plugin.php';
356 }
357 $plugins = array_keys( get_plugins() );
358 $active_plugins = is_network_admin() ? array_keys( get_site_option( 'active_sitewide_plugins', array() ) ) : get_option( 'active_plugins', array() );
359 foreach ( $plugins as $key => $plugin ) {
360 if ( in_array( $plugin, $active_plugins ) ) {
361 unset( $plugins[$key] );
362 }
363 }
364 $body['active_plugins'] = $active_plugins;
365 $body['inactive_plugins'] = $plugins;
366
367 /**
368 * Text Direction.
369 */
370 $body['text_direction'] = ( function_exists( 'is_rtl' ) ? ( is_rtl() ? 'RTL' : 'LTR' ) : 'NOT SET' );
371 /**
372 * Get Our Plugin Data.
373 * @since 3.0.0
374 */
375 $plugin = $this->plugin_data();
376 if( empty( $plugin ) ) {
377 $body['message'] .= __( 'We can\'t detect any plugin information. This is most probably because you have not included the code in the plugin main file.', 'embedpress' );
378 $body['status'] = 'NOT FOUND';
379 } else {
380 if( isset( $plugin['Name'] ) ) {
381 $body['plugin'] = sanitize_text_field( $plugin['Name'] );
382 }
383 if( isset( $plugin['Version'] ) ) {
384 $body['version'] = sanitize_text_field( $plugin['Version'] );
385 }
386 $body['status'] = 'Active';
387 }
388
389 /**
390 * Get our plugin options
391 * @since 1.0.0
392 */
393 // $options = $this->options;
394 // $plugin_options = array();
395 // if( ! empty( $options ) && is_array( $options ) ) {
396 // foreach( $options as $option ) {
397 // $fields = get_option( $option );
398 // // Check for permission to send this option
399 // if( isset( $fields['wpins_registered_setting'] ) ) {
400 // foreach( $fields as $key=>$value ) {
401 // $plugin_options[$key] = $value;
402 // }
403 // }
404 // }
405 // }
406 // $body['plugin_options'] = $this->options; // Returns array
407 // $body['plugin_options_fields'] = $plugin_options; // Returns object
408
409 /**
410 * Get active theme name and version
411 * @since 3.0.0
412 */
413 $theme = wp_get_theme();
414 if( $theme->Name ) {
415 $body['theme'] = sanitize_text_field( $theme->Name );
416 }
417 if( $theme->Version ) {
418 $body['theme_version'] = sanitize_text_field( $theme->Version );
419 }
420 return $body;
421 }
422
423 /**
424 * Collect plugin data,
425 * Retrieve current plugin information
426 *
427 * @since 3.0.0
428 */
429 public function plugin_data() {
430 if( ! function_exists( 'get_plugin_data' ) ) {
431 include ABSPATH . '/wp-admin/includes/plugin.php';
432 }
433 $plugin = get_plugin_data( $this->plugin_file );
434 return $plugin;
435 }
436 /**
437 * Send the data to insights.
438 * @since 3.0.0
439 */
440 public function send_data( $body ) {
441 /**
442 * Get SITE ID
443 */
444 $site_id_key = "wpins_{$this->plugin_name}_site_id";
445 $site_id = get_option( $site_id_key, false );
446 $failed_data = [];
447 $site_url = get_bloginfo( 'url' );
448 $original_site_url = get_option( "wpins_{$this->plugin_name}_original_url", false );
449
450 if( ( $original_site_url === false || $original_site_url != $site_url ) && version_compare( $body['wpins_version'], '3.0.1', '>=' ) ) {
451 $site_id = false;
452 }
453 /**
454 * Send Initial Data to API
455 */
456 if( $site_id == false && $this->item_id !== false ) {
457 if( isset( $_SERVER['REMOTE_ADDR'] ) && ! empty( $_SERVER['REMOTE_ADDR'] && $_SERVER['REMOTE_ADDR'] != '127.0.0.1' ) ) {
458 $country_request = wp_remote_get( 'http://ip-api.com/json/'. $_SERVER['REMOTE_ADDR'] .'?fields=country');
459 if( ! is_wp_error( $country_request ) && $country_request['response']['code'] == 200 ) {
460 $ip_data = json_decode( $country_request["body"] );
461 $body['country'] = isset( $ip_data->country ) ? $ip_data->country : 'NOT SET';
462 }
463 }
464
465 $body['plugin_slug'] = $this->plugin_name;
466 $body['url'] = $site_url;
467 $body['item_id'] = $this->item_id;
468
469 $request = $this->remote_post( $body );
470 if( ! is_wp_error( $request ) && $request['response']['code'] == 200 ) {
471 $retrieved_body = json_decode( wp_remote_retrieve_body( $request ), true );
472 if( is_array( $retrieved_body ) && isset( $retrieved_body['siteId'] ) ) {
473 update_option( $site_id_key, $retrieved_body['siteId'] );
474 update_option( "wpins_{$this->plugin_name}_original_url", $site_url );
475 update_option( "wpins_{$this->plugin_name}_{$retrieved_body['siteId']}", $body );
476 }
477 } else {
478 $failed_data = $body;
479 }
480 }
481
482 $site_id_data_key = "wpins_{$this->plugin_name}_{$site_id}";
483 $site_id_data_failed_key = "wpins_{$this->plugin_name}_{$site_id}_send_failed";
484
485 if( $site_id != false ) {
486 $old_sent_data = get_option( $site_id_data_key, [] );
487 $diff_data = $this->diff( $body, $old_sent_data );
488 $failed_data = get_option( $site_id_data_failed_key, [] );
489 if( ! empty( $failed_data ) && $diff_data != $failed_data ) {
490 $failed_data = array_merge( $failed_data, $diff_data );
491 }
492 }
493
494 if( ! empty( $failed_data ) && $site_id != false ) {
495 $failed_data['plugin_slug'] = $this->plugin_name;
496 $failed_data['url'] = $site_url;
497 $failed_data['site_id'] = $site_id;
498 if( $original_site_url != false ) {
499 $failed_data['original_url'] = $original_site_url;
500 }
501
502 $request = $this->remote_post( $failed_data );
503 if( ! is_wp_error( $request ) ) {
504 delete_option( $site_id_data_failed_key );
505 $replaced_data = array_merge( $old_sent_data, $failed_data );
506 update_option( $site_id_data_key, $replaced_data );
507 }
508 }
509
510 if( ! empty( $diff_data ) && $site_id != false && empty( $failed_data ) ) {
511 $diff_data['plugin_slug'] = $this->plugin_name;
512 $diff_data['url'] = $site_url;
513 $diff_data['site_id'] = $site_id;
514 if( $original_site_url != false ) {
515 $diff_data['original_url'] = $original_site_url;
516 }
517
518 $request = $this->remote_post( $diff_data );
519 if( is_wp_error( $request ) ) {
520 update_option( $site_id_data_failed_key, $diff_data );
521 } else {
522 $replaced_data = array_merge( $old_sent_data, $diff_data );
523 update_option( $site_id_data_key, $replaced_data );
524 }
525 }
526
527 $this->set_track_time();
528
529 if( isset( $request ) && is_wp_error( $request ) ) {
530 return $request;
531 }
532
533 if( isset( $request ) ) {
534 return true;
535 }
536 return false;
537 }
538 /**
539 * WP_REMOTE_POST method responsible for send data to the API_URL
540 *
541 * @param array $data
542 * @param array $args
543 * @return void
544 */
545 protected function remote_post( $data = array(), $args = array() ){
546 if( empty( $data ) ) {
547 return;
548 }
549
550 $args = wp_parse_args( $args, array(
551 'method' => 'POST',
552 'timeout' => 30,
553 'redirection' => 5,
554 'httpversion' => '1.1',
555 'blocking' => true,
556 'body' => $data,
557 'user-agent' => 'PUT/1.0.0; ' . get_bloginfo( 'url' )
558 ));
559 $request = wp_remote_post( esc_url( self::API_URL ), $args );
560 if( is_wp_error( $request ) || ( isset( $request['response'], $request['response']['code'] ) && $request['response']['code'] != 200 ) ) {
561 return new WP_Error( 500, 'Something went wrong.' );
562 }
563 return $request;
564 }
565 /**
566 * Difference between old and new data
567 *
568 * @param array $new_data
569 * @param array $old_data
570 * @return void
571 */
572 protected function diff( $new_data, $old_data ){
573 $data = [];
574 if( ! empty( $new_data ) ) {
575 foreach( $new_data as $key => $value ) {
576 if( isset( $old_data[ $key ] ) ) {
577 if( $old_data[ $key ] == $value ) {
578 continue;
579 }
580 }
581 $data[ $key ] = $value;
582 }
583 }
584 return $data;
585 }
586 /**
587 * Display the admin notice to users to allow them to opt in
588 *
589 * @since 3.0.0
590 */
591 public function notice() {
592 /**
593 * Return if notice is not set.
594 */
595 if( ! isset( $this->notice_options['notice'] ) ) {
596 return;
597 }
598 /**
599 * Check is allowed or blocked for notice.
600 */
601 $block_notice = get_option( 'wpins_block_notice' );
602 if( isset( $block_notice[$this->plugin_name] ) ) {
603 return;
604 }
605 if ( ! current_user_can( 'manage_options' ) ) {
606 return;
607 }
608
609 $url_yes = add_query_arg( [
610 'plugin' => $this->plugin_name,
611 'plugin_action' => 'yes',
612 ] );
613 $url_no = add_query_arg( array(
614 'plugin' => $this->plugin_name,
615 'plugin_action' => 'no'
616 ) );
617
618 // Decide on notice text
619 $notice_text = $this->notice_options['notice'] . ' <a href="#" class="wpinsights-'. $this->plugin_name .'-collect">'. $this->notice_options['consent_button_text'] .'</a>';
620 $extra_notice_text = $this->notice_options['extra_notice'];
621
622 $output = '';
623 $output .= '<div class="notice notice-info updated put-dismiss-notice">';
624 $output .= '<p>'. $notice_text .'</p>';
625 $output .= '<div class="wpinsights-data" style="display: none;">';
626 $output .= '<p>'. $extra_notice_text .'</p>';
627 $output .= '</div>';
628 $output .= '<p>';
629 $output .= '<a href="'. esc_url( $url_yes ) .'" class="button-primary">'. $this->notice_options['yes'] .'</a>&nbsp;';
630 $output .= '<a href="'. esc_url( $url_no ) .'" class="button-secondary">'. $this->notice_options['no'] .'</a>';
631 $output .= '</p>';
632 $output .= "<script type='text/javascript'>jQuery('.wpinsights-". $this->plugin_name ."-collect').on('click', function(e) {e.preventDefault();jQuery('.wpinsights-data').slideToggle('fast');});</script>";
633 $output .= '</div>';
634
635 echo $output;
636 }
637 /**
638 * Set all notice options to customized notice.
639 *
640 * @since 3.0.0
641 * @param array $options
642 * @return void
643 */
644 public function set_notice_options( $options = [] ){
645 $default_options = [
646 'consent_button_text' => __( 'What we collect.', 'embedpress' ),
647 'yes' => __( 'Sure, I\'d like to help', 'embedpress' ),
648 'no' => __( 'No Thanks.', 'embedpress' ),
649 ];
650 $options = wp_parse_args( $options, $default_options );
651 $this->notice_options = $options;
652 }
653 /**
654 * Responsible for track the click from Notice.
655 * @return void
656 */
657 public function clicked(){
658 if( isset( $_GET['plugin'] ) && trim($_GET['plugin']) === $this->plugin_name && isset( $_GET['plugin_action'] ) ) {
659 if( isset( $_GET['tab'] ) && $_GET['tab'] === 'plugin-information' ) {
660 return;
661 }
662 $plugin = sanitize_text_field( $_GET['plugin'] );
663 $action = sanitize_text_field( $_GET['plugin_action'] );
664 if( $action == 'yes' ) {
665 $this->schedule_tracking();
666 $this->set_is_tracking_allowed( true, $plugin );
667 if( $this->do_tracking( true ) ) {
668 $this->update_block_notice( $plugin );
669 }
670 /**
671 * Redirect User To the Current URL, but without set query arguments.
672 */
673 wp_safe_redirect( $this->redirect_to() );
674 } else {
675 $this->set_is_tracking_allowed( false, $plugin );
676 $this->update_block_notice( $plugin );
677 }
678 }
679 }
680 /**
681 * Set if we should block the opt-in notice for this plugin
682 *
683 * @since 3.0.0
684 */
685 public function update_block_notice( $plugin = null ) {
686 if( empty( $plugin ) ) {
687 $plugin = $this->plugin_name;
688 }
689 $block_notice = get_option( 'wpins_block_notice' );
690 if( empty( $block_notice ) || ! is_array( $block_notice ) ) {
691 $block_notice = array( $plugin => $plugin );
692 } else {
693 $block_notice[$plugin] = $plugin;
694 }
695 update_option( 'wpins_block_notice', $block_notice );
696 }
697 /**
698 * AJAX callback when the deactivated form is submitted.
699 * @since 3.0.0
700 */
701 public function deactivate_reasons_form_submit() {
702 check_ajax_referer( 'wpins_deactivation_nonce', 'security' );
703 if( isset( $_POST['values'] ) ) {
704 $values = $_POST['values'];
705 update_option( 'wpins_deactivation_reason_' . $this->plugin_name, $values );
706 }
707 if( isset( $_POST['details'] ) ) {
708 $details = sanitize_text_field( $_POST['details'] );
709 update_option( 'wpins_deactivation_details_' . $this->plugin_name, $details );
710 }
711 echo 'success';
712 wp_die();
713 }
714 /**
715 * Filter the deactivation link to allow us to present a form when the user deactivates the plugin
716 * @since 3.0.0
717 */
718 public function deactivate_action_links( $links ) {
719 /**
720 * Check is tracking allowed or not.
721 */
722 if( ! $this->is_tracking_allowed() ) {
723 return $links;
724 }
725 if( isset( $links['deactivate'] ) && $this->include_goodbye_form ) {
726 $deactivation_link = $links['deactivate'];
727 /**
728 * Change the default deactivate button link.
729 */
730 $deactivation_link = str_replace( '<a ', '<div class="wpinsights-goodbye-form-wrapper-'. esc_attr( $this->plugin_name ) .'"><div class="wpinsights-goodbye-form-bg"></div><span class="wpinsights-goodbye-form" id="wpinsights-goodbye-form"></span></div><a onclick="javascript:event.preventDefault();" id="wpinsights-goodbye-link-' . esc_attr( $this->plugin_name ) . '" ', $deactivation_link );
731 $links['deactivate'] = $deactivation_link;
732 }
733 return $links;
734 }
735 /**
736 * ALL Deactivate Reasons.
737 * @since 3.0.0
738 */
739 public function deactivation_reasons() {
740 $form = array();
741 $form['heading'] = __( 'Sorry to see you go', 'embedpress' );
742 $form['body'] = __( 'Before you deactivate the plugin, would you quickly give us your reason for doing so?', 'embedpress' );
743
744 $form['options'] = array(
745 __( 'I no longer need the plugin', 'embedpress' ),
746 [
747 'label' => __( 'I found a better plugin', 'embedpress' ),
748 'extra_field' => __( 'Please share which plugin', 'embedpress' )
749 ],
750 __( "I couldn't get the plugin to work", 'embedpress' ),
751 __( 'It\'s a temporary deactivation', 'embedpress' ),
752 [
753 'label' => __( 'Other', 'embedpress' ),
754 'extra_field' => __( 'Please share the reason', 'embedpress' ),
755 'type' => 'textarea'
756 ]
757 );
758 return apply_filters( 'wpins_form_text_' . $this->plugin_name, $form );
759 }
760 /**
761 * Deactivate Reasons Form.
762 * This form will appears when user wants to deactivate the plugin to send you deactivated reasons.
763 *
764 * @since 3.0.0
765 */
766 public function deactivate_reasons_form() {
767 $form = $this->deactivation_reasons();
768 $class_plugin_name = esc_attr( $this->plugin_name );
769 $html = '<div class="wpinsights-goodbye-form-head"><strong>' . esc_html( $form['heading'] ) . '</strong></div>';
770 $html .= '<div class="wpinsights-goodbye-form-body"><p class="wpinsights-goodbye-form-caption">' . esc_html( $form['body'] ) . '</p>';
771 if( is_array( $form['options'] ) ) {
772 $html .= '<div id="wpinsights-goodbye-options" class="wpinsights-goodbye-options"><ul>';
773 foreach( $form['options'] as $option ) {
774 if( is_array( $option ) ) {
775 $id = strtolower( str_replace( " ", "_", esc_attr( $option['label'] ) ) );
776 $id = $id . '_' . $class_plugin_name;
777 $html .= '<li class="has-goodbye-extra">';
778 $html .= '<input type="radio" name="wpinsights-'. $class_plugin_name .'-goodbye-options" id="' . $id . '" value="' . esc_attr( $option['label'] ) . '">';
779 $html .= '<div><label for="' . $id . '">' . esc_attr( $option['label'] ) . '</label>';
780 if( isset( $option[ 'extra_field' ] ) && ! isset( $option['type'] )) {
781 $html .= '<input type="text" style="display: none" name="'. $id .'" id="' . str_replace( " ", "", esc_attr( $option['extra_field'] ) ) . '" placeholder="' . esc_attr( $option['extra_field'] ) . '">';
782 }
783 if( isset( $option[ 'extra_field' ] ) && isset( $option['type'] )) {
784 $html .= '<'. $option['type'] .' style="display: none" type="text" name="'. $id .'" id="' . str_replace( " ", "", esc_attr( $option['extra_field'] ) ) . '" placeholder="' . esc_attr( $option['extra_field'] ) . '"></' . $option['type'] . '>';
785 }
786 $html .= '</div></li>';
787 } else {
788 $id = strtolower( str_replace( " ", "_", esc_attr( $option ) ) );
789 $id = $id . '_' . $class_plugin_name;
790 $html .= '<li><input type="radio" name="wpinsights-'. $class_plugin_name .'-goodbye-options" id="' . $id . '" value="' . esc_attr( $option ) . '"> <label for="' . $id . '">' . esc_attr( $option ) . '</label></li>';
791 }
792 }
793 $html .= '</ul></div><!-- .wpinsights-'. $class_plugin_name .'-goodbye-options -->';
794 }
795 $html .= '</div><!-- .wpinsights-goodbye-form-body -->';
796 $html .= '<p class="deactivating-spinner"><span class="spinner"></span> ' . __( 'Submitting form', 'embedpress' ) . '</p>';
797
798 $wrapper_class = '.wpinsights-goodbye-form-wrapper-'. $class_plugin_name;
799
800 $styles = '';
801 $styles .= '<style type="text/css">';
802 $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' .wpinsights-goodbye-form-bg {';
803 $styles .= 'background: rgba( 0, 0, 0, .8 );position: fixed;top: 0;left: 0;width: 100%;height: 100%;z-index: 9;';
804 $styles .= '}';
805 $styles .= $wrapper_class . '{';
806 $styles .= 'position: relative; display: none;';
807 $styles .= '}';
808 $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' ' . $wrapper_class . '{';
809 $styles .= 'display: flex !important; position: fixed;top: 0;left: 0;width: 100%;height: 100%; justify-content: center; align-items: center;';
810 $styles .= '}';
811 $styles .= $wrapper_class . ' .wpinsights-goodbye-form { display: none; }';
812 $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' .wpinsights-goodbye-form {';
813 $styles .= 'position: relative !important; width: 550px; max-width: 80%; background: #fff; box-shadow: 2px 8px 23px 3px rgba(0,0,0,.2); border-radius: 3px; white-space: normal; overflow: hidden; display: block; z-index: 999999;';
814 $styles .= '}';
815 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-head {';
816 $styles .= 'background: #fff; color: #495157; padding: 18px; box-shadow: 0 0 8px rgba(0,0,0,.1); font-size: 15px;';
817 $styles .= '}';
818 $styles .= $wrapper_class . ' .wpinsights-goodbye-form .wpinsights-goodbye-form-head strong { font-size: 15px; }';
819 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body { padding: 8px 18px; color: #333; }';
820 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body label { padding-left: 5px; color: #6d7882; }';
821 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body .wpinsights-goodbye-form-caption {';
822 $styles .= 'font-weight: 500; font-size: 15px; color: #495157; line-height: 1.4;';
823 $styles .= '}';
824 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options { padding-top: 5px; }';
825 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li { margin-bottom: 15px; }';
826 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div { display: inline; padding-left: 3px; }';
827 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > input, '. $wrapper_class .' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > textarea {';
828 $styles .= 'margin: 10px 18px; padding: 8px; width: 80%;';
829 $styles .= '}';
830 $styles .= $wrapper_class . ' .deactivating-spinner { display: none; padding-bottom: 20px !important; }';
831 $styles .= $wrapper_class . ' .deactivating-spinner .spinner { float: none; margin: 4px 4px 0 18px; vertical-align: bottom; visibility: visible; }';
832 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer { padding: 8px 18px; margin-bottom: 15px; }';
833 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer > .wpinsights-goodbye-form-buttons { display: flex; align-items: center; justify-content: space-between; }';
834 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-submit-btn {';
835 $styles .= 'background-color: #d30c5c; -webkit-border-radius: 3px; border-radius: 3px; color: #fff; line-height: 1; padding: 15px 20px; font-size: 13px;';
836 $styles .= '}';
837 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-deactivate-btn {';
838 $styles .= 'font-size: 13px; color: #a4afb7; background: none; float: right; padding-right: 10px; width: auto; text-decoration: underline;';
839 $styles .= '}';
840 $styles .= $wrapper_class . ' .test {';
841 $styles .= '}';
842 $styles .= '</style>';
843 $styles .= '';
844
845 echo $styles;
846 ?>
847 <script type="text/javascript">
848 jQuery(document).ready(function($){
849 $("#wpinsights-goodbye-link-<?php echo $class_plugin_name; ?>").on("click",function(){
850 // We'll send the user to this deactivation link when they've completed or dismissed the form
851 var url = document.getElementById("wpinsights-goodbye-link-<?php echo $class_plugin_name; ?>");
852 $('body').toggleClass('wpinsights-form-active-<?php echo $class_plugin_name; ?>');
853 $(".wpinsights-goodbye-form-wrapper-<?php echo $class_plugin_name; ?> #wpinsights-goodbye-form").fadeIn();
854 $(".wpinsights-goodbye-form-wrapper-<?php echo $class_plugin_name; ?> #wpinsights-goodbye-form").html( '<?php echo $html; ?>' + '<div class="wpinsights-goodbye-form-footer"><div class="wpinsights-goodbye-form-buttons"><a id="wpinsights-submit-form-<?php echo $class_plugin_name; ?>" class="wpinsights-submit-btn" href="#"><?php _e( 'Submit and Deactivate', 'embedpress' ); ?></a>&nbsp;<a class="wpsp-put-deactivate-btn" href="'+url+'"><?php _e( 'Just Deactivate', 'embedpress' ); ?></a></div></div>');
855 $('#wpinsights-submit-form-<?php echo $class_plugin_name; ?>').on('click', function(e){
856 // As soon as we click, the body of the form should disappear
857 $("#wpinsights-goodbye-form-<?php echo $class_plugin_name; ?> .wpinsights-goodbye-form-body").fadeOut();
858 $("#wpinsights-goodbye-form-<?php echo $class_plugin_name; ?> .wpinsights-goodbye-form-footer").fadeOut();
859 // Fade in spinner
860 $("#wpinsights-goodbye-form-<?php echo $class_plugin_name; ?> .deactivating-spinner").fadeIn();
861 e.preventDefault();
862 var checkedInput = $("input[name='wpinsights-<?php echo $class_plugin_name; ?>-goodbye-options']:checked"),
863 checkedInputVal, details;
864 if( checkedInput.length > 0 ) {
865 checkedInputVal = checkedInput.val();
866 details = $('input[name="'+ checkedInput[0].id +'"], textarea[name="'+ checkedInput[0].id +'"]').val();
867 }
868
869 if( typeof details === 'undefined' ) {
870 details = '';
871 }
872 if( typeof checkedInputVal === 'undefined' ) {
873 checkedInputVal = 'No Reason';
874 }
875
876 var data = {
877 'action': 'deactivation_form_<?php echo $class_plugin_name; ?>',
878 'values': checkedInputVal,
879 'details': details,
880 'security': "<?php echo wp_create_nonce ( 'wpins_deactivation_nonce' ); ?>",
881 'dataType': "json"
882 }
883
884 $.post(
885 ajaxurl,
886 data,
887 function(response){
888 // Redirect to original deactivation URL
889 window.location.href = url;
890 }
891 );
892 });
893 $('#wpinsights-goodbye-options > ul ').on('click', 'li label, li > input', function( e ){
894 var parent = $(this).parents('li');
895 parent.siblings().find('label').next('input, textarea').css('display', 'none');
896 parent.find('label').next('input, textarea').css('display', 'block');
897 });
898 // If we click outside the form, the form will close
899 $('.wpinsights-goodbye-form-bg').on('click',function(){
900 $("#wpinsights-goodbye-form").fadeOut();
901 $('body').removeClass('wpinsights-form-active-<?php echo $class_plugin_name; ?>');
902 });
903 });
904 });
905 </script>
906 <?php }
907 }
908 endif;