PluginProbe ʕ •ᴥ•ʔ
EmbedPress – PDF Embedder, 3D PDF FlipBook, Google Reviews, YouTube Videos, Upload & Embed PDF documents / 4.6.0
EmbedPress – PDF Embedder, 3D PDF FlipBook, Google Reviews, YouTube Videos, Upload & Embed PDF documents v4.6.0
4.6.0 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
Analytics 2 weeks ago Database 2 months ago DynamicFieldResolver.php 1 month ago Elementor_Enhancer.php 6 months ago EmbedPress_Core_Installer.php 6 years ago EmbedPress_Notice.php 3 months ago EmbedPress_Plugin_Usage_Tracker.php 1 month ago Extend_CustomPlayer_Controls.php 2 months ago Extend_Elementor_Controls.php 1 year ago FeatureNoticeManager.php 4 days ago FeatureNotices.php 4 days ago FeaturePreviewModal.php 4 days ago Feature_Enhancer.php 1 month ago GoogleReviewsAdminPage.php 4 days ago GoogleReviewsApify.php 4 days ago GoogleReviewsManaged.php 4 days ago GoogleReviewsRenderer.php 4 days ago GoogleReviewsRestController.php 4 days ago GoogleReviewsStore.php 4 days ago Helper.php 4 days ago Pdf_Thumbnail_Handler.php 2 months ago PermalinkHelper.php 10 months ago View_Count_Display.php 2 weeks ago
EmbedPress_Plugin_Usage_Tracker.php
985 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 if (class_exists('\\EmbedPress\\Includes\\Classes\\Helper')) {
425 \EmbedPress\Includes\Classes\Helper::seed_source_data_from_existing_content();
426 }
427 $body['optional_data'] = $this->get_count_source_data('elementor_source_data', 'gutenberg_source_data');
428
429 /**
430 * Get active theme name and version
431 * @since 3.0.0
432 */
433 $theme = wp_get_theme();
434 if( $theme->Name ) {
435 $body['theme'] = sanitize_text_field( $theme->Name );
436 }
437 if( $theme->Version ) {
438 $body['theme_version'] = sanitize_text_field( $theme->Version );
439 }
440 return $body;
441 }
442
443 /**
444 * This method is responsible for couting source data.
445 *
446 * @since 3.6.6
447 */
448
449 public function get_count_source_data($elementor_source_option_name, $gutenbert_source_option_name) {
450
451 $elementor_sources = json_decode(get_option($elementor_source_option_name), true);
452 $gutenberg_sources = json_decode(get_option($gutenbert_source_option_name), true);
453
454 $e_counts = [];
455 $g_counts = [];
456 $counts = [];
457
458 $elementor_option_name = str_replace("_source_data", "", $elementor_source_option_name);
459 $gutenberg_option_name = str_replace("_source_data", "", $gutenbert_source_option_name);
460
461 foreach ($elementor_sources as $item) {
462 if (isset($item['source']['name'])) {
463 $name = strtolower(str_replace(' ', '-', $item['source']['name'])); // normalize source name
464 $e_counts["$elementor_option_name-$name"] = isset($e_counts["$elementor_option_name-$name"]) ? $e_counts["$elementor_option_name-$name"] + 1 : 1;
465 }
466 }
467
468 foreach ($gutenberg_sources as $item) {
469 if (isset($item['source']['name'])) {
470 $name = strtolower(str_replace(' ', '-', $item['source']['name'])); // normalize source name
471 $g_counts["$gutenberg_option_name-$name"] = isset($g_counts["$gutenberg_option_name-$name"]) ? $g_counts["$gutenberg_option_name-$name"] + 1 : 1;
472 }
473 }
474
475 $counts = array_merge($e_counts, $g_counts);
476
477 return $counts;
478 }
479
480 /**
481 * Collect plugin data,
482 * Retrieve current plugin information
483 *
484 * @since 3.0.0
485 */
486 public function plugin_data() {
487 if( ! function_exists( 'get_plugin_data' ) ) {
488 include ABSPATH . '/wp-admin/includes/plugin.php';
489 }
490 $plugin = get_plugin_data( $this->plugin_file );
491 return $plugin;
492 }
493 /**
494 * Send the data to insights.
495 * @since 3.0.0
496 */
497 public function send_data( $body ) {
498 /**
499 * Get SITE ID
500 */
501 $site_id_key = "wpins_{$this->plugin_name}_site_id";
502 $site_id = get_option( $site_id_key, false );
503 $failed_data = [];
504 $site_url = get_bloginfo( 'url' );
505 $original_site_url = get_option( "wpins_{$this->plugin_name}_original_url", false );
506
507 if( ( $original_site_url === false || $original_site_url != $site_url ) && version_compare( $body['wpins_version'], '3.0.1', '>=' ) ) {
508 $site_id = false;
509 }
510 /**
511 * Send Initial Data to API
512 */
513 if( $site_id == false && $this->item_id !== false ) {
514 if( isset( $_SERVER['REMOTE_ADDR'] ) && ! empty( $_SERVER['REMOTE_ADDR'] && $_SERVER['REMOTE_ADDR'] != '127.0.0.1' ) ) {
515 $country_request = wp_remote_get( 'http://ip-api.com/json/'. $_SERVER['REMOTE_ADDR'] .'?fields=country');
516 if( ! is_wp_error( $country_request ) && $country_request['response']['code'] == 200 ) {
517 $ip_data = json_decode( $country_request["body"] );
518 $body['country'] = isset( $ip_data->country ) ? $ip_data->country : 'NOT SET';
519 }
520 }
521
522 $body['plugin_slug'] = $this->plugin_name;
523 $body['url'] = $site_url;
524 $body['item_id'] = $this->item_id;
525
526 $request = $this->remote_post( $body );
527 if( ! is_wp_error( $request ) && $request['response']['code'] == 200 ) {
528 $retrieved_body = json_decode( wp_remote_retrieve_body( $request ), true );
529 if( is_array( $retrieved_body ) && isset( $retrieved_body['siteId'] ) ) {
530 update_option( $site_id_key, $retrieved_body['siteId'] );
531 update_option( "wpins_{$this->plugin_name}_original_url", $site_url );
532 update_option( "wpins_{$this->plugin_name}_{$retrieved_body['siteId']}", $body );
533 }
534 } else {
535 $failed_data = $body;
536 }
537 }
538
539 $site_id_data_key = "wpins_{$this->plugin_name}_{$site_id}";
540 $site_id_data_failed_key = "wpins_{$this->plugin_name}_{$site_id}_send_failed";
541
542 if( $site_id != false ) {
543 $old_sent_data = get_option( $site_id_data_key, [] );
544 $diff_data = $this->diff( $body, $old_sent_data );
545 $failed_data = get_option( $site_id_data_failed_key, [] );
546 if( ! empty( $failed_data ) && $diff_data != $failed_data ) {
547 $failed_data = array_merge( $failed_data, $diff_data );
548 }
549 }
550
551 if( ! empty( $failed_data ) && $site_id != false ) {
552 $failed_data['plugin_slug'] = $this->plugin_name;
553 $failed_data['url'] = $site_url;
554 $failed_data['site_id'] = $site_id;
555 if( $original_site_url != false ) {
556 $failed_data['original_url'] = $original_site_url;
557 }
558
559 $request = $this->remote_post( $failed_data );
560 if( ! is_wp_error( $request ) ) {
561 delete_option( $site_id_data_failed_key );
562 $replaced_data = array_merge( $old_sent_data, $failed_data );
563 update_option( $site_id_data_key, $replaced_data );
564 }
565 }
566
567 if( ! empty( $diff_data ) && $site_id != false && empty( $failed_data ) ) {
568 $diff_data['plugin_slug'] = $this->plugin_name;
569 $diff_data['url'] = $site_url;
570 $diff_data['site_id'] = $site_id;
571 if( $original_site_url != false ) {
572 $diff_data['original_url'] = $original_site_url;
573 }
574
575 $request = $this->remote_post( $diff_data );
576 if( is_wp_error( $request ) ) {
577 update_option( $site_id_data_failed_key, $diff_data );
578 } else {
579 $replaced_data = array_merge( $old_sent_data, $diff_data );
580 update_option( $site_id_data_key, $replaced_data );
581 }
582 }
583
584 $this->set_track_time();
585
586 if( isset( $request ) && is_wp_error( $request ) ) {
587 return $request;
588 }
589
590 if( isset( $request ) ) {
591 return true;
592 }
593 return false;
594 }
595 /**
596 * WP_REMOTE_POST method responsible for send data to the API_URL
597 *
598 * @param array $data
599 * @param array $args
600 * @return void
601 */
602 protected function remote_post( $data = array(), $args = array() ){
603 if( empty( $data ) ) {
604 return;
605 }
606
607 $args = wp_parse_args( $args, array(
608 'method' => 'POST',
609 'timeout' => 30,
610 'redirection' => 5,
611 'httpversion' => '1.1',
612 'blocking' => true,
613 'body' => $data,
614 'user-agent' => 'PUT/1.0.0; ' . get_bloginfo( 'url' )
615 ));
616 $request = wp_remote_post( esc_url( self::API_URL ), $args );
617 if( is_wp_error( $request ) || ( isset( $request['response'], $request['response']['code'] ) && $request['response']['code'] != 200 ) ) {
618 return new WP_Error( 500, 'Something went wrong.' );
619 }
620 return $request;
621 }
622 /**
623 * Difference between old and new data
624 *
625 * @param array $new_data
626 * @param array $old_data
627 * @return void
628 */
629 protected function diff( $new_data, $old_data ){
630 $data = [];
631 if( ! empty( $new_data ) ) {
632 foreach( $new_data as $key => $value ) {
633 if( isset( $old_data[ $key ] ) ) {
634 if( $old_data[ $key ] == $value ) {
635 continue;
636 }
637 }
638 $data[ $key ] = $value;
639 }
640 }
641 return $data;
642 }
643 /**
644 * Display the admin notice to users to allow them to opt in
645 *
646 * @since 3.0.0
647 */
648 public function notice() {
649 /**
650 * Return if notice is not set.
651 */
652 if( ! isset( $this->notice_options['notice'] ) ) {
653 return;
654 }
655 /**
656 * Check is allowed or blocked for notice.
657 */
658 $block_notice = get_option( 'wpins_block_notice' );
659 if( isset( $block_notice[$this->plugin_name] ) ) {
660 return;
661 }
662
663 if( ! \function_exists('wp_get_current_user') ) {
664 require_once ABSPATH . "wp-includes/pluggable.php";
665 }
666
667 if ( ! current_user_can( 'manage_options' ) ) {
668 return;
669 }
670
671 $url_yes = add_query_arg( [
672 'plugin' => $this->plugin_name,
673 'plugin_action' => 'yes',
674 ] );
675 $url_no = add_query_arg( array(
676 'plugin' => $this->plugin_name,
677 'plugin_action' => 'no'
678 ) );
679
680 $url_yes = wp_nonce_url( $url_yes, '_wpnonce_optin_' . $this->plugin_name );
681 $url_no = wp_nonce_url( $url_no, '_wpnonce_optin_' . $this->plugin_name );
682
683 // Decide on notice text
684 $notice_text = $this->notice_options['notice'] . ' <a href="#" class="wpinsights-'. $this->plugin_name .'-collect">'. $this->notice_options['consent_button_text'] .'</a>';
685 $extra_notice_text = $this->notice_options['extra_notice'];
686
687 $output = '';
688 $output .= '<div class="embedpress-optin">';
689 $output .= '<p>'. $notice_text .'</p>';
690 $output .= '<div class="wpinsights-data" style="display: none;">';
691 $output .= '<p>'. $extra_notice_text .'</p>';
692 $output .= '</div>';
693 $output .= '<p>';
694 $output .= '<a href="'. esc_url( $url_yes ) .'" class="button-primary">'. $this->notice_options['yes'] .'</a>&nbsp;';
695 $output .= '<a href="'. esc_url( $url_no ) .'" class="button-secondary">'. $this->notice_options['no'] .'</a>';
696 $output .= '</p>';
697 $output .= "<script type='text/javascript'>jQuery('.wpinsights-". $this->plugin_name ."-collect').on('click', function(e) {e.preventDefault();jQuery('.wpinsights-data').slideToggle('fast');});</script>";
698 $output .= '</div>';
699
700 echo $output;
701 }
702 /**
703 * Set all notice options to customized notice.
704 *
705 * @since 3.0.0
706 * @param array $options
707 * @return void
708 */
709 public function set_notice_options( $options = [] ){
710 $default_options = [
711 'consent_button_text' => 'What we collect.',
712 'yes' => 'Sure, I\'d like to help',
713 'no' => 'No Thanks.',
714 ];
715 $options = wp_parse_args( $options, $default_options );
716 $this->notice_options = $options;
717 }
718
719 /**
720 * Responsible for track the click from Notice.
721 * @return void
722 */
723 public function clicked( $notice = null ){
724 if( isset( $_GET[ '_wpnonce' ] ) && isset( $_GET['plugin'] ) && trim($_GET['plugin']) === $this->plugin_name && isset( $_GET['plugin_action'] ) ) {
725 if( isset( $_GET['tab'] ) && $_GET['tab'] === 'plugin-information' ) {
726 return;
727 }
728
729 if( ! wp_verify_nonce( $_GET[ '_wpnonce' ], '_wpnonce_optin_' . $this->plugin_name ) ) {
730 return;
731 }
732
733 $plugin = sanitize_text_field( $_GET['plugin'] );
734 $action = sanitize_text_field( $_GET['plugin_action'] );
735 if( $action == 'yes' ) {
736 $this->schedule_tracking();
737 $this->set_is_tracking_allowed( true, $plugin );
738 if( $this->do_tracking( true ) ) {
739 $this->update_block_notice( $plugin );
740 if( ! is_null ( $notice ) ) {
741 $notice->dismiss->dismiss_notice();
742 }
743 }
744 } else {
745 $this->set_is_tracking_allowed( false, $plugin );
746 $this->update_block_notice( $plugin );
747 if( ! is_null ( $notice ) ) {
748 $notice->dismiss->dismiss_notice();
749 }
750 }
751 /**
752 * Redirect User To the Current URL, but without set query arguments.
753 */
754 wp_safe_redirect( $this->redirect_to() );
755 }
756 }
757 /**
758 * Set if we should block the opt-in notice for this plugin
759 *
760 * @since 3.0.0
761 */
762 public function update_block_notice( $plugin = null ) {
763 if( empty( $plugin ) ) {
764 $plugin = $this->plugin_name;
765 }
766 $block_notice = get_option( 'wpins_block_notice' );
767 if( empty( $block_notice ) || ! is_array( $block_notice ) ) {
768 $block_notice = array( $plugin => $plugin );
769 } else {
770 $block_notice[$plugin] = $plugin;
771 }
772 update_option( 'wpins_block_notice', $block_notice );
773 }
774 /**
775 * AJAX callback when the deactivated form is submitted.
776 * @since 3.0.0
777 */
778 public function deactivate_reasons_form_submit() {
779 check_ajax_referer( 'wpins_deactivation_nonce', 'security' );
780 if( isset( $_POST['values'] ) ) {
781 $values = $_POST['values'];
782 update_option( 'wpins_deactivation_reason_' . $this->plugin_name, $values );
783 }
784 if( isset( $_POST['details'] ) ) {
785 $details = sanitize_text_field( $_POST['details'] );
786 update_option( 'wpins_deactivation_details_' . $this->plugin_name, $details );
787 }
788 echo 'success';
789 wp_die();
790 }
791 /**
792 * Filter the deactivation link to allow us to present a form when the user deactivates the plugin
793 * @since 3.0.0
794 */
795 public function deactivate_action_links( $links ) {
796 /**
797 * Check is tracking allowed or not.
798 */
799 if( ! $this->is_tracking_allowed() ) {
800 return $links;
801 }
802 if( isset( $links['deactivate'] ) && $this->include_goodbye_form ) {
803 $deactivation_link = $links['deactivate'];
804 /**
805 * Change the default deactivate button link.
806 */
807 $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 );
808 $links['deactivate'] = $deactivation_link;
809 }
810 return $links;
811 }
812 /**
813 * ALL Deactivate Reasons.
814 * @since 3.0.0
815 */
816 public function deactivation_reasons() {
817 $form = array();
818 $form['heading'] = __( 'Sorry to see you go', 'embedpress' );
819 $form['body'] = __( 'Before you deactivate the plugin, would you quickly give us your reason for doing so?', 'embedpress' );
820
821 $form['options'] = array(
822 __( 'I no longer need the plugin', 'embedpress' ),
823 [
824 'label' => __( 'I found a better plugin', 'embedpress' ),
825 'extra_field' => __( 'Please share which plugin', 'embedpress' )
826 ],
827 __( "I couldn't get the plugin to work", 'embedpress' ),
828 __( 'It\'s a temporary deactivation', 'embedpress' ),
829 [
830 'label' => __( 'Other', 'embedpress' ),
831 'extra_field' => __( 'Please share the reason', 'embedpress' ),
832 'type' => 'textarea'
833 ]
834 );
835 return apply_filters( 'wpins_form_text_' . $this->plugin_name, $form );
836 }
837 /**
838 * Deactivate Reasons Form.
839 * This form will appears when user wants to deactivate the plugin to send you deactivated reasons.
840 *
841 * @since 3.0.0
842 */
843 public function deactivate_reasons_form() {
844 $form = $this->deactivation_reasons();
845 $class_plugin_name = esc_attr( $this->plugin_name );
846 $html = '<div class="wpinsights-goodbye-form-head"><strong>' . esc_html( $form['heading'] ) . '</strong></div>';
847 $html .= '<div class="wpinsights-goodbye-form-body"><p class="wpinsights-goodbye-form-caption">' . esc_html( $form['body'] ) . '</p>';
848 if( is_array( $form['options'] ) ) {
849 $html .= '<div id="wpinsights-goodbye-options" class="wpinsights-goodbye-options"><ul>';
850 foreach( $form['options'] as $option ) {
851 if( is_array( $option ) ) {
852 $id = strtolower( str_replace( " ", "_", esc_attr( $option['label'] ) ) );
853 $id = $id . '_' . $class_plugin_name;
854 $html .= '<li class="has-goodbye-extra">';
855 $html .= '<input type="radio" name="wpinsights-'. $class_plugin_name .'-goodbye-options" id="' . $id . '" value="' . esc_attr( $option['label'] ) . '">';
856 $html .= '<div><label for="' . $id . '">' . esc_attr( $option['label'] ) . '</label>';
857 if( isset( $option[ 'extra_field' ] ) && ! isset( $option['type'] )) {
858 $html .= '<input type="text" style="display: none" name="'. $id .'" id="' . str_replace( " ", "", esc_attr( $option['extra_field'] ) ) . '" placeholder="' . esc_attr( $option['extra_field'] ) . '">';
859 }
860 if( isset( $option[ 'extra_field' ] ) && isset( $option['type'] )) {
861 $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'] . '>';
862 }
863 $html .= '</div></li>';
864 } else {
865 $id = strtolower( str_replace( " ", "_", esc_attr( $option ) ) );
866 $id = $id . '_' . $class_plugin_name;
867 $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>';
868 }
869 }
870 $html .= '</ul></div><!-- .wpinsights-'. $class_plugin_name .'-goodbye-options -->';
871 }
872 $html .= '</div><!-- .wpinsights-goodbye-form-body -->';
873 $html .= '<p class="deactivating-spinner"><span class="spinner"></span> ' . __( 'Submitting form', 'embedpress' ) . '</p>';
874
875 $wrapper_class = '.wpinsights-goodbye-form-wrapper-'. $class_plugin_name;
876
877 $styles = '';
878 $styles .= '<style type="text/css">';
879 $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' .wpinsights-goodbye-form-bg {';
880 $styles .= 'background: rgba( 0, 0, 0, .8 );position: fixed;top: 0;left: 0;width: 100%;height: 100%;z-index: 9;';
881 $styles .= '}';
882 $styles .= $wrapper_class . '{';
883 $styles .= 'position: relative; display: none;';
884 $styles .= '}';
885 $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' ' . $wrapper_class . '{';
886 $styles .= 'display: flex !important; position: fixed;top: 0;left: 0;width: 100%;height: 100%; justify-content: center; align-items: center; z-index: 99999;';
887 $styles .= '}';
888 $styles .= $wrapper_class . ' .wpinsights-goodbye-form { display: none; }';
889 $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' .wpinsights-goodbye-form {';
890 $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;';
891 $styles .= '}';
892 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-head {';
893 $styles .= 'background: #fff; color: #495157; padding: 18px; box-shadow: 0 0 8px rgba(0,0,0,.1); font-size: 15px;';
894 $styles .= '}';
895 $styles .= $wrapper_class . ' .wpinsights-goodbye-form .wpinsights-goodbye-form-head strong { font-size: 15px; }';
896 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body { padding: 8px 18px; color: #333; }';
897 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body label { padding-left: 5px; color: #6d7882; }';
898 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body .wpinsights-goodbye-form-caption {';
899 $styles .= 'font-weight: 500; font-size: 15px; color: #495157; line-height: 1.4;';
900 $styles .= '}';
901 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options { padding-top: 5px; }';
902 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li { margin-bottom: 15px; }';
903 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div { display: inline; padding-left: 3px; }';
904 $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 {';
905 $styles .= 'margin: 10px 18px; padding: 8px; width: 80%;';
906 $styles .= '}';
907 $styles .= $wrapper_class . ' .deactivating-spinner { display: none; padding-bottom: 20px !important; }';
908 $styles .= $wrapper_class . ' .deactivating-spinner .spinner { float: none; margin: 4px 4px 0 18px; vertical-align: bottom; visibility: visible; }';
909 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer { padding: 8px 18px; margin-bottom: 15px; }';
910 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer > .wpinsights-goodbye-form-buttons { display: flex; align-items: center; justify-content: space-between; }';
911 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-submit-btn {';
912 $styles .= 'background-color: #d30c5c; -webkit-border-radius: 3px; border-radius: 3px; color: #fff; line-height: 1; padding: 15px 20px; font-size: 13px;';
913 $styles .= '}';
914 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-deactivate-btn {';
915 $styles .= 'font-size: 13px; color: #a4afb7; background: none; float: right; padding-right: 10px; width: auto; text-decoration: underline;';
916 $styles .= '}';
917 $styles .= $wrapper_class . ' .test {';
918 $styles .= '}';
919 $styles .= '</style>';
920 $styles .= '';
921
922 echo $styles;
923 ?>
924 <script type="text/javascript">
925 jQuery(document).ready(function($){
926 $("#wpinsights-goodbye-link-<?php echo $class_plugin_name; ?>").on("click",function(){
927 // We'll send the user to this deactivation link when they've completed or dismissed the form
928 var url = document.getElementById("wpinsights-goodbye-link-<?php echo $class_plugin_name; ?>");
929 $('body').toggleClass('wpinsights-form-active-<?php echo $class_plugin_name; ?>');
930 $(".wpinsights-goodbye-form-wrapper-<?php echo $class_plugin_name; ?> #wpinsights-goodbye-form").fadeIn();
931 $(".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>');
932 $('#wpinsights-submit-form-<?php echo $class_plugin_name; ?>').on('click', function(e){
933 // As soon as we click, the body of the form should disappear
934 $("#wpinsights-goodbye-form-<?php echo $class_plugin_name; ?> .wpinsights-goodbye-form-body").fadeOut();
935 $("#wpinsights-goodbye-form-<?php echo $class_plugin_name; ?> .wpinsights-goodbye-form-footer").fadeOut();
936 // Fade in spinner
937 $("#wpinsights-goodbye-form-<?php echo $class_plugin_name; ?> .deactivating-spinner").fadeIn();
938 e.preventDefault();
939 var checkedInput = $("input[name='wpinsights-<?php echo $class_plugin_name; ?>-goodbye-options']:checked"),
940 checkedInputVal, details;
941 if( checkedInput.length > 0 ) {
942 checkedInputVal = checkedInput.val();
943 details = $('input[name="'+ checkedInput[0].id +'"], textarea[name="'+ checkedInput[0].id +'"]').val();
944 }
945
946 if( typeof details === 'undefined' ) {
947 details = '';
948 }
949 if( typeof checkedInputVal === 'undefined' ) {
950 checkedInputVal = 'No Reason';
951 }
952
953 var data = {
954 'action': 'deactivation_form_<?php echo $class_plugin_name; ?>',
955 'values': checkedInputVal,
956 'details': details,
957 'security': "<?php echo wp_create_nonce ( 'wpins_deactivation_nonce' ); ?>",
958 'dataType': "json"
959 }
960
961 $.post(
962 ajaxurl,
963 data,
964 function(response){
965 // Redirect to original deactivation URL
966 window.location.href = url;
967 }
968 );
969 });
970 $('#wpinsights-goodbye-options > ul ').on('click', 'li label, li > input', function( e ){
971 var parent = $(this).parents('li');
972 parent.siblings().find('label').next('input, textarea').css('display', 'none');
973 parent.find('label').next('input, textarea').css('display', 'block');
974 });
975 // If we click outside the form, the form will close
976 $('.wpinsights-goodbye-form-bg').on('click',function(){
977 $("#wpinsights-goodbye-form").fadeOut();
978 $('body').removeClass('wpinsights-form-active-<?php echo $class_plugin_name; ?>');
979 });
980 });
981 });
982 </script>
983 <?php }
984 }
985 endif;