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