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