API
17 hours ago
Admin
17 hours ago
Blocks
17 hours ago
CLI
17 hours ago
Container
17 hours ago
Data
17 hours ago
Integrations
17 hours ago
REST
17 hours ago
Theme
17 hours ago
Tools
17 hours ago
Whatsit
17 hours ago
Config_Handler.php
17 hours ago
Integration.php
17 hours ago
Permissions.php
17 hours ago
Pod_Manager.php
17 hours ago
Service_Provider.php
17 hours ago
Service_Provider_Base.php
17 hours ago
Service_Provider_Fallback.php
17 hours ago
Static_Cache.php
17 hours ago
Whatsit.php
17 hours ago
Wisdom_Tracker.php
17 hours ago
Wisdom_Tracker.php
854 lines
| 1 | <?php |
| 2 | |
| 3 | namespace Pods; |
| 4 | |
| 5 | /** |
| 6 | * Wisdom Tracker class. |
| 7 | * |
| 8 | * @link https://wisdomplugin.com/ |
| 9 | * |
| 10 | * @since 2.8.0 |
| 11 | */ |
| 12 | class Wisdom_Tracker { |
| 13 | |
| 14 | private $wisdom_version = '1.2.5'; |
| 15 | private $home_url = ''; |
| 16 | private $plugin_file = ''; |
| 17 | private $plugin_name = ''; |
| 18 | private $options = []; |
| 19 | private $require_optin = true; |
| 20 | private $include_goodbye_form = true; |
| 21 | private $marketing = false; |
| 22 | private $collect_email = false; |
| 23 | private $what_am_i = 'plugin'; |
| 24 | private $theme_allows_tracking = 0; |
| 25 | |
| 26 | /** |
| 27 | * Class constructor |
| 28 | * |
| 29 | * @param $_home_url The URL to the site we're sending data to |
| 30 | * @param $_plugin_slug The slug for this plugin (SKC modification for Pods). |
| 31 | * @param $_plugin_file The file path for this plugin |
| 32 | * @param $_options Plugin options to track |
| 33 | * @param $_require_optin Whether user opt-in is required (always required on WordPress.org) |
| 34 | * @param $_include_goodbye_form Whether to include a form when the user deactivates |
| 35 | * @param $_marketing Marketing method: |
| 36 | * 0: Don't collect email addresses |
| 37 | * 1: Request permission same time as tracking opt-in |
| 38 | * 2: Request permission after opt-in |
| 39 | */ |
| 40 | public function __construct( |
| 41 | $_plugin_file, $_plugin_slug, $_home_url, $_options, $_require_optin = true, $_include_goodbye_form = true, $_marketing = false |
| 42 | ) { |
| 43 | $this->plugin_file = $_plugin_file; |
| 44 | $this->home_url = trailingslashit( $_home_url ); |
| 45 | |
| 46 | // If the filename is 'functions' then we're tracking a theme |
| 47 | if ( basename( $this->plugin_file, '.php' ) != 'functions' ) { |
| 48 | $this->plugin_name = basename( $this->plugin_file, '.php' ); |
| 49 | |
| 50 | // SKC modification for Pods. |
| 51 | if ( ! empty( $_plugin_slug ) ) { |
| 52 | $this->plugin_name = $_plugin_slug; |
| 53 | } |
| 54 | } else { |
| 55 | $this->what_am_i = 'theme'; |
| 56 | $theme = wp_get_theme(); |
| 57 | if ( $theme->Name ) { |
| 58 | $this->plugin_name = sanitize_text_field( $theme->Name ); |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | $this->options = $_options; |
| 63 | $this->require_optin = $_require_optin; |
| 64 | $this->include_goodbye_form = $_include_goodbye_form; |
| 65 | $this->marketing = $_marketing; |
| 66 | |
| 67 | // Only use this on switching theme |
| 68 | $this->theme_allows_tracking = get_theme_mod( 'wisdom-allow-tracking', 0 ); |
| 69 | |
| 70 | // Schedule / deschedule tracking when activated / deactivated |
| 71 | if ( $this->what_am_i == 'theme' ) { |
| 72 | // Need to think about scheduling for sites that have already activated the theme |
| 73 | add_action( 'after_switch_theme', [ $this, 'schedule_tracking' ] ); |
| 74 | add_action( 'switch_theme', [ $this, 'deactivate_this_plugin' ] ); |
| 75 | } else { |
| 76 | register_activation_hook( $this->plugin_file, [ $this, 'schedule_tracking' ] ); |
| 77 | register_deactivation_hook( $this->plugin_file, [ $this, 'deactivate_this_plugin' ] ); |
| 78 | } |
| 79 | |
| 80 | // Get it going |
| 81 | $this->init(); |
| 82 | } |
| 83 | |
| 84 | public function init() { |
| 85 | // Check marketing |
| 86 | if ( $this->marketing == 3 ) { |
| 87 | $this->set_can_collect_email( true, $this->plugin_name ); |
| 88 | } |
| 89 | |
| 90 | // Check whether opt-in is required |
| 91 | // If not, then tracking is allowed |
| 92 | if ( ! $this->require_optin ) { |
| 93 | $this->set_can_collect_email( true, $this->plugin_name ); |
| 94 | $this->set_is_tracking_allowed( true ); |
| 95 | $this->update_block_notice(); |
| 96 | $this->do_tracking(); |
| 97 | } |
| 98 | |
| 99 | // Hook our do_tracking function to the weekly action |
| 100 | add_filter( 'cron_schedules', [ $this, 'schedule_weekly_event' ] ); |
| 101 | // It's called weekly, but in fact it could be daily, weekly or monthly |
| 102 | add_action( 'put_do_weekly_action', [ $this, 'do_tracking' ] ); |
| 103 | |
| 104 | // Use this action for local testing |
| 105 | // add_action( 'admin_init', array( $this, 'do_tracking' ) ); |
| 106 | |
| 107 | // Display the admin notice on activation |
| 108 | add_action( 'admin_init', [ $this, 'set_notification_time' ] ); |
| 109 | add_action( 'admin_notices', [ $this, 'optin_notice' ] ); |
| 110 | } |
| 111 | |
| 112 | /** |
| 113 | * When the plugin is activated |
| 114 | * Create scheduled event |
| 115 | * And check if tracking is enabled - perhaps the plugin has been reactivated |
| 116 | * |
| 117 | * @since 1.0.0 |
| 118 | */ |
| 119 | public function schedule_tracking() { |
| 120 | if ( ! wp_next_scheduled( 'put_do_weekly_action' ) ) { |
| 121 | $schedule = $this->get_schedule(); |
| 122 | wp_schedule_event( time(), $schedule, 'put_do_weekly_action' ); |
| 123 | } |
| 124 | $this->do_tracking( true ); |
| 125 | } |
| 126 | |
| 127 | /** |
| 128 | * Create weekly schedule |
| 129 | * |
| 130 | * @since 1.2.3 |
| 131 | */ |
| 132 | public function schedule_weekly_event( $schedules ) { |
| 133 | $schedules['weekly'] = [ |
| 134 | 'interval' => 604800, |
| 135 | 'display' => __( 'Once Weekly' ), |
| 136 | ]; |
| 137 | $schedules['monthly'] = [ |
| 138 | 'interval' => 2635200, |
| 139 | 'display' => __( 'Once Monthly' ), |
| 140 | ]; |
| 141 | |
| 142 | return $schedules; |
| 143 | } |
| 144 | |
| 145 | /** |
| 146 | * Get how frequently data is tracked back |
| 147 | * |
| 148 | * @since 1.2.3 |
| 149 | */ |
| 150 | public function get_schedule() { |
| 151 | // Could be daily, weekly or monthly |
| 152 | $schedule = apply_filters( 'wisdom_filter_schedule_' . $this->plugin_name, 'monthly' ); |
| 153 | |
| 154 | return $schedule; |
| 155 | } |
| 156 | |
| 157 | /** |
| 158 | * This is our function to get everything going |
| 159 | * Check that user has opted in |
| 160 | * Collect data |
| 161 | * Then send it back |
| 162 | * |
| 163 | * @since 1.0.0 |
| 164 | * |
| 165 | * @param $force Force tracking if it's not time |
| 166 | */ |
| 167 | public function do_tracking( $force = false ) { |
| 168 | // If the home site hasn't been defined, we just drop out. Nothing much we can do. |
| 169 | if ( ! $this->home_url ) { |
| 170 | return; |
| 171 | } |
| 172 | |
| 173 | // Check to see if the user has opted in to tracking |
| 174 | $allow_tracking = $this->get_is_tracking_allowed(); |
| 175 | if ( ! $allow_tracking ) { |
| 176 | return; |
| 177 | } |
| 178 | |
| 179 | // Check to see if it's time to track |
| 180 | $track_time = $this->get_is_time_to_track(); |
| 181 | if ( ! $track_time && ! $force ) { |
| 182 | return; |
| 183 | } |
| 184 | |
| 185 | $this->set_admin_email(); |
| 186 | |
| 187 | // Get our data |
| 188 | $body = $this->get_data(); |
| 189 | |
| 190 | // Send the data |
| 191 | $this->send_data( $body ); |
| 192 | } |
| 193 | |
| 194 | /** |
| 195 | * We hook this to admin_init when the user accepts tracking |
| 196 | * Ensures the email address is available |
| 197 | * |
| 198 | * @since 1.2.1 |
| 199 | */ |
| 200 | public function force_tracking() { |
| 201 | $this->do_tracking( true ); // Run this straightaway |
| 202 | } |
| 203 | |
| 204 | /** |
| 205 | * Send the data to the home site |
| 206 | * |
| 207 | * @since 1.0.0 |
| 208 | */ |
| 209 | public function send_data( $body ) { |
| 210 | $request = wp_remote_post( esc_url( $this->home_url . '?usage_tracker=hello' ), [ |
| 211 | 'method' => 'POST', |
| 212 | 'timeout' => 20, |
| 213 | 'redirection' => 5, |
| 214 | 'httpversion' => '1.1', |
| 215 | 'blocking' => true, |
| 216 | 'body' => $body, |
| 217 | 'user-agent' => 'PUT/1.0.0; ' . home_url(), |
| 218 | ] ); |
| 219 | |
| 220 | $this->set_track_time(); |
| 221 | |
| 222 | if ( is_wp_error( $request ) ) { |
| 223 | return $request; |
| 224 | } |
| 225 | } |
| 226 | |
| 227 | /** |
| 228 | * Here we collect most of the data |
| 229 | * |
| 230 | * @since 1.0.0 |
| 231 | */ |
| 232 | public function get_data() { |
| 233 | // Use this to pass error messages back if necessary |
| 234 | $body['message'] = ''; |
| 235 | |
| 236 | // Use this array to send data back |
| 237 | $body = [ |
| 238 | 'plugin_slug' => sanitize_text_field( $this->plugin_name ), |
| 239 | 'url' => home_url(), |
| 240 | 'site_name' => get_bloginfo( 'name' ), |
| 241 | 'site_version' => get_bloginfo( 'version' ), |
| 242 | 'site_language' => get_bloginfo( 'language' ), |
| 243 | 'charset' => get_bloginfo( 'charset' ), |
| 244 | 'wisdom_version' => $this->wisdom_version, |
| 245 | 'php_version' => phpversion(), |
| 246 | 'multisite' => is_multisite(), |
| 247 | 'file_location' => __FILE__, |
| 248 | 'product_type' => esc_html( $this->what_am_i ), |
| 249 | ]; |
| 250 | |
| 251 | // Collect the email if the correct option has been set |
| 252 | if ( $this->get_can_collect_email() ) { |
| 253 | $body['email'] = $this->get_admin_email(); |
| 254 | } |
| 255 | $body['marketing_method'] = $this->marketing; |
| 256 | |
| 257 | $body['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : ''; |
| 258 | |
| 259 | // Extra PHP fields |
| 260 | $body['memory_limit'] = ini_get( 'memory_limit' ); |
| 261 | $body['upload_max_size'] = ini_get( 'upload_max_size' ); |
| 262 | $body['post_max_size'] = ini_get( 'post_max_size' ); |
| 263 | $body['upload_max_filesize'] = ini_get( 'upload_max_filesize' ); |
| 264 | $body['max_execution_time'] = ini_get( 'max_execution_time' ); |
| 265 | $body['max_input_time'] = ini_get( 'max_input_time' ); |
| 266 | |
| 267 | // Retrieve current plugin information |
| 268 | if ( ! function_exists( 'get_plugins' ) ) { |
| 269 | include ABSPATH . '/wp-admin/includes/plugin.php'; |
| 270 | } |
| 271 | |
| 272 | $plugins = array_keys( get_plugins() ); |
| 273 | // @todo SKC customization: Contribute back to Wisdom project. |
| 274 | $active_plugins = (array) get_option( 'active_plugins', [] ); |
| 275 | |
| 276 | foreach ( $plugins as $key => $plugin ) { |
| 277 | if ( in_array( $plugin, $active_plugins ) ) { |
| 278 | // Remove active plugins from list so we can show active and inactive separately |
| 279 | unset( $plugins[ $key ] ); |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | $body['active_plugins'] = $active_plugins; |
| 284 | $body['inactive_plugins'] = $plugins; |
| 285 | |
| 286 | // Check text direction |
| 287 | $body['text_direction'] = 'LTR'; |
| 288 | if ( function_exists( 'is_rtl' ) ) { |
| 289 | if ( is_rtl() ) { |
| 290 | $body['text_direction'] = 'RTL'; |
| 291 | } |
| 292 | } else { |
| 293 | $body['text_direction'] = 'not set'; |
| 294 | } |
| 295 | |
| 296 | /** |
| 297 | * Get our plugin data |
| 298 | * Currently we grab plugin name and version |
| 299 | * Or, return a message if the plugin data is not available |
| 300 | * |
| 301 | * @since 1.0.0 |
| 302 | */ |
| 303 | $plugin = $this->plugin_data(); |
| 304 | $body['status'] = 'Active'; // Never translated |
| 305 | if ( empty( $plugin ) ) { |
| 306 | // We can't find the plugin data |
| 307 | // Send a message back to our home site |
| 308 | $body['message'] .= __( 'We can\'t detect any product information. This is most probably because you have not included the code snippet.', 'pods' ); |
| 309 | $body['status'] = 'Data not found'; // Never translated |
| 310 | } else { |
| 311 | if ( isset( $plugin['Name'] ) ) { |
| 312 | $body['plugin'] = sanitize_text_field( $plugin['Name'] ); |
| 313 | } |
| 314 | if ( isset( $plugin['Version'] ) ) { |
| 315 | $body['version'] = sanitize_text_field( $plugin['Version'] ); |
| 316 | } |
| 317 | } |
| 318 | |
| 319 | /** |
| 320 | * Get our plugin options |
| 321 | * |
| 322 | * @since 1.0.0 |
| 323 | */ |
| 324 | $options = $this->options; |
| 325 | $plugin_options = []; |
| 326 | if ( ! empty( $options ) && is_array( $options ) ) { |
| 327 | foreach ( $options as $option ) { |
| 328 | $fields = get_option( $option ); |
| 329 | // Check for permission to send this option |
| 330 | if ( isset( $fields['wisdom_registered_setting'] ) ) { |
| 331 | foreach ( $fields as $key => $value ) { |
| 332 | $plugin_options[ $key ] = $value; |
| 333 | } |
| 334 | } |
| 335 | } |
| 336 | } |
| 337 | $body['plugin_options'] = $this->options; // Returns array |
| 338 | $body['plugin_options_fields'] = $plugin_options; // Returns object |
| 339 | |
| 340 | /** |
| 341 | * Get our theme data |
| 342 | * Currently we grab theme name and version |
| 343 | * |
| 344 | * @since 1.0.0 |
| 345 | */ |
| 346 | $theme = wp_get_theme(); |
| 347 | if ( $theme->Name ) { |
| 348 | $body['theme'] = sanitize_text_field( $theme->Name ); |
| 349 | } |
| 350 | if ( $theme->Version ) { |
| 351 | $body['theme_version'] = sanitize_text_field( $theme->Version ); |
| 352 | } |
| 353 | if ( $theme->Template ) { |
| 354 | $body['theme_parent'] = sanitize_text_field( $theme->Template ); |
| 355 | } |
| 356 | |
| 357 | // Return the data |
| 358 | return $body; |
| 359 | } |
| 360 | |
| 361 | /** |
| 362 | * Return plugin data |
| 363 | * |
| 364 | * @since 1.0.0 |
| 365 | */ |
| 366 | public function plugin_data() { |
| 367 | // Being cautious here |
| 368 | if ( ! function_exists( 'get_plugin_data' ) ) { |
| 369 | include ABSPATH . '/wp-admin/includes/plugin.php'; |
| 370 | } |
| 371 | // Retrieve current plugin information |
| 372 | $plugin = get_plugin_data( $this->plugin_file ); |
| 373 | |
| 374 | return $plugin; |
| 375 | } |
| 376 | |
| 377 | /** |
| 378 | * Deactivating plugin |
| 379 | * |
| 380 | * @since 1.0.0 |
| 381 | */ |
| 382 | public function deactivate_this_plugin() { |
| 383 | // Check to see if the user has opted in to tracking |
| 384 | if ( $this->what_am_i == 'theme' ) { |
| 385 | $allow_tracking = $this->theme_allows_tracking; |
| 386 | } else { |
| 387 | $allow_tracking = $this->get_is_tracking_allowed(); |
| 388 | } |
| 389 | |
| 390 | if ( ! $allow_tracking ) { |
| 391 | return; |
| 392 | } |
| 393 | |
| 394 | $body = $this->get_data(); |
| 395 | $body['status'] = 'Deactivated'; // Never translated |
| 396 | $body['deactivated_date'] = time(); |
| 397 | |
| 398 | // Add deactivation form data |
| 399 | if ( false !== get_option( 'wisdom_deactivation_reason_' . $this->plugin_name ) ) { |
| 400 | $body['deactivation_reason'] = get_option( 'wisdom_deactivation_reason_' . $this->plugin_name ); |
| 401 | } |
| 402 | if ( false !== get_option( 'wisdom_deactivation_details_' . $this->plugin_name ) ) { |
| 403 | $body['deactivation_details'] = get_option( 'wisdom_deactivation_details_' . $this->plugin_name ); |
| 404 | } |
| 405 | |
| 406 | $this->send_data( $body ); |
| 407 | // Clear scheduled update |
| 408 | wp_clear_scheduled_hook( 'put_do_weekly_action' ); |
| 409 | |
| 410 | // Clear the wisdom_last_track_time value for this plugin |
| 411 | // @since 1.2.2 |
| 412 | $track_time = get_option( 'wisdom_last_track_time' ); |
| 413 | if ( isset( $track_time[ $this->plugin_name ] ) ) { |
| 414 | unset( $track_time[ $this->plugin_name ] ); |
| 415 | } |
| 416 | update_option( 'wisdom_last_track_time', $track_time, 'yes' ); |
| 417 | } |
| 418 | |
| 419 | /** |
| 420 | * Is tracking allowed? |
| 421 | * |
| 422 | * @since 1.0.0 |
| 423 | */ |
| 424 | public function get_is_tracking_allowed() { |
| 425 | // First, check if the user has changed their mind and opted out of tracking |
| 426 | if ( $this->has_user_opted_out() ) { |
| 427 | $this->set_is_tracking_allowed( false, $this->plugin_name ); |
| 428 | |
| 429 | // SKC modification for Pods. |
| 430 | $this->set_can_collect_email( false, $this->plugin_name ); |
| 431 | |
| 432 | return false; |
| 433 | } |
| 434 | |
| 435 | if ( $this->what_am_i == 'theme' ) { |
| 436 | $mod = get_theme_mod( 'wisdom-allow-tracking', 0 ); |
| 437 | if ( $mod ) { |
| 438 | return true; |
| 439 | } |
| 440 | } else { |
| 441 | // The wisdom_allow_tracking option is an array of plugins that are being tracked |
| 442 | $allow_tracking = get_option( 'wisdom_allow_tracking' ); |
| 443 | // If this plugin is in the array, then tracking is allowed |
| 444 | if ( isset( $allow_tracking[ $this->plugin_name ] ) ) { |
| 445 | return true; |
| 446 | } |
| 447 | } |
| 448 | |
| 449 | return false; |
| 450 | } |
| 451 | |
| 452 | /** |
| 453 | * Set if tracking is allowed |
| 454 | * Option is an array of all plugins with tracking permitted |
| 455 | * More than one plugin may be using the tracker |
| 456 | * |
| 457 | * @since 1.0.0 |
| 458 | * |
| 459 | * @param $is_allowed Boolean true if tracking is allowed, false if not |
| 460 | */ |
| 461 | public function set_is_tracking_allowed( $is_allowed, $plugin = null ) { |
| 462 | if ( empty( $plugin ) ) { |
| 463 | $plugin = $this->plugin_name; |
| 464 | } |
| 465 | |
| 466 | // The wisdom_allow_tracking option is an array of plugins that are being tracked |
| 467 | $allow_tracking = get_option( 'wisdom_allow_tracking' ); |
| 468 | |
| 469 | // If the user has decided to opt out |
| 470 | if ( $this->has_user_opted_out() ) { |
| 471 | if ( $this->what_am_i == 'theme' ) { |
| 472 | set_theme_mod( 'wisdom-allow-tracking', 0 ); |
| 473 | } else { |
| 474 | if ( isset( $allow_tracking[ $plugin ] ) ) { |
| 475 | unset( $allow_tracking[ $plugin ] ); |
| 476 | } |
| 477 | } |
| 478 | } elseif ( $is_allowed || ! $this->require_optin ) { |
| 479 | // If the user has agreed to allow tracking or if opt-in is not required |
| 480 | |
| 481 | if ( $this->what_am_i == 'theme' ) { |
| 482 | set_theme_mod( 'wisdom-allow-tracking', 1 ); |
| 483 | } else { |
| 484 | if ( empty( $allow_tracking ) || ! is_array( $allow_tracking ) ) { |
| 485 | // If nothing exists in the option yet, start a new array with the plugin name |
| 486 | $allow_tracking = [ $plugin => $plugin ]; |
| 487 | } else { |
| 488 | // Else add the plugin name to the array |
| 489 | $allow_tracking[ $plugin ] = $plugin; |
| 490 | } |
| 491 | } |
| 492 | } else { |
| 493 | if ( $this->what_am_i == 'theme' ) { |
| 494 | set_theme_mod( 'wisdom-allow-tracking', 0 ); |
| 495 | } else { |
| 496 | if ( isset( $allow_tracking[ $plugin ] ) ) { |
| 497 | unset( $allow_tracking[ $plugin ] ); |
| 498 | } |
| 499 | } |
| 500 | } |
| 501 | |
| 502 | update_option( 'wisdom_allow_tracking', $allow_tracking, 'yes' ); |
| 503 | } |
| 504 | |
| 505 | /** |
| 506 | * Has the user opted out of allowing tracking? |
| 507 | * Note that themes are opt in / plugins are opt out |
| 508 | * |
| 509 | * @since 1.1.0 |
| 510 | * @return Boolean |
| 511 | */ |
| 512 | public function has_user_opted_out() { |
| 513 | // Different opt-out methods for plugins and themes |
| 514 | if ( $this->what_am_i == 'theme' ) { |
| 515 | // Look for the theme mod |
| 516 | $mod = get_theme_mod( 'wisdom-allow-tracking', 0 ); |
| 517 | if ( false === $mod ) { |
| 518 | // If the theme mod is not set, then return true - the user has opted out |
| 519 | return true; |
| 520 | } |
| 521 | } else { |
| 522 | // Iterate through the options that are being tracked looking for wisdom_opt_out setting |
| 523 | if ( ! empty( $this->options ) ) { |
| 524 | foreach ( $this->options as $option_name ) { |
| 525 | // Check each option |
| 526 | $options = get_option( $option_name ); |
| 527 | // If we find the setting, return true |
| 528 | if ( ! empty( $options['wisdom_opt_out'] ) ) { |
| 529 | return true; |
| 530 | } |
| 531 | } |
| 532 | } |
| 533 | } |
| 534 | |
| 535 | return false; |
| 536 | } |
| 537 | |
| 538 | /** |
| 539 | * Check if it's time to track |
| 540 | * |
| 541 | * @since 1.1.1 |
| 542 | */ |
| 543 | public function get_is_time_to_track() { |
| 544 | // Let's see if we're due to track this plugin yet |
| 545 | // @todo SKC customization: Contribute back to Wisdom project. |
| 546 | $track_times = (array) get_option( 'wisdom_last_track_time', [] ); |
| 547 | if ( ! isset( $track_times[ $this->plugin_name ] ) ) { |
| 548 | // If we haven't set a time for this plugin yet, then we must track it |
| 549 | return true; |
| 550 | } else { |
| 551 | // If the time is set, let's get our schedule and check if it's time to track |
| 552 | $schedule = $this->get_schedule(); |
| 553 | if ( $schedule == 'daily' ) { |
| 554 | $period = 'day'; |
| 555 | } elseif ( $schedule == 'weekly' ) { |
| 556 | $period = 'week'; |
| 557 | } else { |
| 558 | $period = 'month'; |
| 559 | } |
| 560 | if ( $track_times[ $this->plugin_name ] < strtotime( '-1 ' . $period ) ) { |
| 561 | return true; |
| 562 | } |
| 563 | } |
| 564 | |
| 565 | return false; |
| 566 | } |
| 567 | |
| 568 | /** |
| 569 | * Record the time we send tracking data |
| 570 | * |
| 571 | * @since 1.1.1 |
| 572 | */ |
| 573 | public function set_track_time() { |
| 574 | // We've tracked, so record the time |
| 575 | // @todo SKC customization: Contribute back to Wisdom project. |
| 576 | $track_times = (array) get_option( 'wisdom_last_track_time', [] ); |
| 577 | // Set different times according to plugin, in case we are tracking multiple plugins |
| 578 | $track_times[ $this->plugin_name ] = time(); |
| 579 | update_option( 'wisdom_last_track_time', $track_times, 'yes' ); |
| 580 | } |
| 581 | |
| 582 | /** |
| 583 | * Set the time when we can display the opt-in notification |
| 584 | * Will display now unless filtered |
| 585 | * |
| 586 | * @since 1.2.4 |
| 587 | */ |
| 588 | public function set_notification_time() { |
| 589 | // @todo SKC customization: Contribute back to Wisdom project. |
| 590 | $notification_times = (array) get_option( 'wisdom_notification_times', [] ); |
| 591 | |
| 592 | // Set different times according to plugin, in case we are tracking multiple plugins |
| 593 | if ( ! isset( $notification_times[ $this->plugin_name ] ) ) { |
| 594 | $delay_notification = apply_filters( 'wisdom_delay_notification_' . $this->plugin_name, 0 ); |
| 595 | // We can delay the notification time |
| 596 | $notification_time = time() + absint( $delay_notification ); |
| 597 | $notification_times[ $this->plugin_name ] = $notification_time; |
| 598 | update_option( 'wisdom_notification_times', $notification_times, 'yes' ); |
| 599 | } |
| 600 | } |
| 601 | |
| 602 | /** |
| 603 | * Get whether it's time to display the notification |
| 604 | * |
| 605 | * @since 1.2.4 |
| 606 | * @return Boolean |
| 607 | */ |
| 608 | public function get_is_notification_time() { |
| 609 | // @todo SKC customization: Contribute back to Wisdom project. |
| 610 | $notification_times = (array) get_option( 'wisdom_notification_times', [] ); |
| 611 | $time = time(); |
| 612 | // Set different times according to plugin, in case we are tracking multiple plugins |
| 613 | if ( isset( $notification_times[ $this->plugin_name ] ) ) { |
| 614 | $notification_time = $notification_times[ $this->plugin_name ]; |
| 615 | if ( $time >= $notification_time ) { |
| 616 | return true; |
| 617 | } |
| 618 | } |
| 619 | |
| 620 | return false; |
| 621 | } |
| 622 | |
| 623 | /** |
| 624 | * Set if we should block the opt-in notice for this plugin |
| 625 | * Option is an array of all plugins that have received a response from the user |
| 626 | * |
| 627 | * @since 1.0.0 |
| 628 | */ |
| 629 | public function update_block_notice( $plugin = null ) { |
| 630 | if ( empty( $plugin ) ) { |
| 631 | $plugin = $this->plugin_name; |
| 632 | } |
| 633 | $block_notice = get_option( 'wisdom_block_notice' ); |
| 634 | if ( empty( $block_notice ) || ! is_array( $block_notice ) ) { |
| 635 | // If nothing exists in the option yet, start a new array with the plugin name |
| 636 | $block_notice = [ $plugin => $plugin ]; |
| 637 | } else { |
| 638 | // Else add the plugin name to the array |
| 639 | $block_notice[ $plugin ] = $plugin; |
| 640 | } |
| 641 | update_option( 'wisdom_block_notice', $block_notice, 'yes' ); |
| 642 | } |
| 643 | |
| 644 | /** |
| 645 | * Can we collect the email address? |
| 646 | * |
| 647 | * @since 1.0.0 |
| 648 | */ |
| 649 | public function get_can_collect_email() { |
| 650 | // The wisdom_collect_email option is an array of plugins that are being tracked |
| 651 | $collect_email = get_option( 'wisdom_collect_email' ); |
| 652 | // If this plugin is in the array, then we can collect the email address |
| 653 | if ( isset( $collect_email[ $this->plugin_name ] ) ) { |
| 654 | return true; |
| 655 | } |
| 656 | |
| 657 | return false; |
| 658 | } |
| 659 | |
| 660 | /** |
| 661 | * Set if user has allowed us to collect their email address |
| 662 | * Option is an array of all plugins with email collection permitted |
| 663 | * More than one plugin may be using the tracker |
| 664 | * |
| 665 | * @since 1.0.0 |
| 666 | * |
| 667 | * @param $can_collect Boolean true if collection is allowed, false if not |
| 668 | */ |
| 669 | public function set_can_collect_email( $can_collect, $plugin = null ) { |
| 670 | if ( empty( $plugin ) ) { |
| 671 | $plugin = $this->plugin_name; |
| 672 | } |
| 673 | // The wisdom_collect_email option is an array of plugins that are being tracked |
| 674 | $collect_email = get_option( 'wisdom_collect_email' ); |
| 675 | // If the user has agreed to allow tracking or if opt-in is not required |
| 676 | if ( $can_collect ) { |
| 677 | if ( empty( $collect_email ) || ! is_array( $collect_email ) ) { |
| 678 | // If nothing exists in the option yet, start a new array with the plugin name |
| 679 | $collect_email = [ $plugin => $plugin ]; |
| 680 | } else { |
| 681 | // Else add the plugin name to the array |
| 682 | $collect_email[ $plugin ] = $plugin; |
| 683 | } |
| 684 | } else { |
| 685 | if ( isset( $collect_email[ $plugin ] ) ) { |
| 686 | unset( $collect_email[ $plugin ] ); |
| 687 | } |
| 688 | } |
| 689 | update_option( 'wisdom_collect_email', $collect_email, 'yes' ); |
| 690 | } |
| 691 | |
| 692 | /** |
| 693 | * Get the correct email address to use |
| 694 | * |
| 695 | * @since 1.1.2 |
| 696 | * @return Email address |
| 697 | */ |
| 698 | public function get_admin_email() { |
| 699 | // The wisdom_collect_email option is an array of plugins that are being tracked |
| 700 | $email = get_option( 'wisdom_admin_emails' ); |
| 701 | // If this plugin is in the array, then we can collect the email address |
| 702 | if ( isset( $email[ $this->plugin_name ] ) ) { |
| 703 | return $email[ $this->plugin_name ]; |
| 704 | } |
| 705 | |
| 706 | return false; |
| 707 | } |
| 708 | |
| 709 | /** |
| 710 | * Set the correct email address to use |
| 711 | * There might be more than one admin on the site |
| 712 | * So we only use the first admin's email address |
| 713 | * |
| 714 | * @since 1.1.2 |
| 715 | * |
| 716 | * @param $plugin Plugin name to set email address for |
| 717 | * @param $email Email address to set |
| 718 | */ |
| 719 | public function set_admin_email( $email = null, $plugin = null ) { |
| 720 | if ( empty( $plugin ) ) { |
| 721 | $plugin = $this->plugin_name; |
| 722 | } |
| 723 | // If no email address passed, try to get the current user's email |
| 724 | if ( empty( $email ) ) { |
| 725 | // Have to check that current user object is available |
| 726 | if ( function_exists( 'wp_get_current_user' ) ) { |
| 727 | $current_user = wp_get_current_user(); |
| 728 | $email = $current_user->user_email; |
| 729 | } |
| 730 | } |
| 731 | // The wisdom_admin_emails option is an array of admin email addresses |
| 732 | $admin_emails = get_option( 'wisdom_admin_emails' ); |
| 733 | if ( empty( $admin_emails ) || ! is_array( $admin_emails ) ) { |
| 734 | // If nothing exists in the option yet, start a new array with the plugin name |
| 735 | $admin_emails = [ $plugin => sanitize_email( $email ) ]; |
| 736 | } elseif ( empty( $admin_emails[ $plugin ] ) ) { |
| 737 | // Else add the email address to the array, if not already set |
| 738 | $admin_emails[ $plugin ] = sanitize_email( $email ); |
| 739 | } |
| 740 | update_option( 'wisdom_admin_emails', $admin_emails ); |
| 741 | } |
| 742 | |
| 743 | /** |
| 744 | * Display the admin notice to users to allow them to opt in |
| 745 | * |
| 746 | * @since 1.0.0 |
| 747 | */ |
| 748 | public function optin_notice() { |
| 749 | // Check for plugin args |
| 750 | if ( |
| 751 | ! empty( $_GET['wisdom_plugin'] ) |
| 752 | && ! empty( $_GET['wisdom_plugin_action'] ) |
| 753 | && ! empty( $_GET['wisdom_plugin_nonce'] ) |
| 754 | && wp_verify_nonce( $_GET['wisdom_plugin_nonce'], 'wisdom_plugin_action' ) |
| 755 | ) { |
| 756 | $plugin = sanitize_text_field( $_GET['wisdom_plugin'] ); |
| 757 | $action = sanitize_text_field( $_GET['wisdom_plugin_action'] ); |
| 758 | if ( $action === 'yes' ) { |
| 759 | $this->set_is_tracking_allowed( true, $plugin ); |
| 760 | // Run this straightaway |
| 761 | add_action( 'admin_init', [ $this, 'force_tracking' ] ); |
| 762 | } else { |
| 763 | $this->set_is_tracking_allowed( false, $plugin ); |
| 764 | } |
| 765 | $this->update_block_notice( $plugin ); |
| 766 | } |
| 767 | |
| 768 | // Is it time to display the notification? |
| 769 | $is_time = $this->get_is_notification_time(); |
| 770 | if ( ! $is_time ) { |
| 771 | return false; |
| 772 | } |
| 773 | |
| 774 | // Check whether to block the notice, e.g. because we're in a local environment |
| 775 | // wisdom_block_notice works the same as wisdom_allow_tracking, an array of plugin names |
| 776 | $block_notice = get_option( 'wisdom_block_notice' ); |
| 777 | |
| 778 | if ( isset( $block_notice[ $this->plugin_name ] ) ) { |
| 779 | return; |
| 780 | } |
| 781 | |
| 782 | if ( ! current_user_can( 'manage_options' ) ) { |
| 783 | return; |
| 784 | } |
| 785 | |
| 786 | // @credit EDD |
| 787 | // Don't bother asking user to opt in if they're in local dev |
| 788 | $is_local = false; |
| 789 | if ( stristr( network_site_url( '/' ), '.dev' ) !== false || stristr( network_site_url( '/' ), 'localhost' ) !== false || stristr( network_site_url( '/' ), ':8888' ) !== false ) { |
| 790 | $is_local = true; |
| 791 | } |
| 792 | $is_local = apply_filters( 'wisdom_is_local_' . $this->plugin_name, $is_local ); |
| 793 | if ( $is_local ) { |
| 794 | $this->update_block_notice(); |
| 795 | |
| 796 | // SKC modification for Pods. |
| 797 | if ( $this->marketing ) { |
| 798 | $this->set_can_collect_email( false ); |
| 799 | } |
| 800 | } else { |
| 801 | // Display the notice requesting permission to track |
| 802 | // Retrieve current plugin information |
| 803 | $plugin = $this->plugin_data(); |
| 804 | $plugin_name = $plugin['Name']; |
| 805 | |
| 806 | $nonce = wp_create_nonce( 'wisdom_plugin_action' ); |
| 807 | |
| 808 | // Args to add to query if user opts in to tracking |
| 809 | $yes_args = [ |
| 810 | 'wisdom_plugin' => $this->plugin_name, |
| 811 | 'wisdom_plugin_action' => 'yes', |
| 812 | 'wisdom_plugin_nonce' => $nonce, |
| 813 | ]; |
| 814 | |
| 815 | // Decide how to request permission to collect email addresses |
| 816 | if ( (int) $this->marketing === 1 ) { |
| 817 | // Option 1 combines permissions to track and collect email |
| 818 | $yes_args['wisdom_marketing_optin'] = 'yes'; |
| 819 | } elseif ( (int) $this->marketing === 2 ) { |
| 820 | // Option 2 enables a second notice that fires after the user opts in to tracking |
| 821 | $yes_args['wisdom_marketing'] = 'yes'; |
| 822 | } |
| 823 | $url_yes = add_query_arg( $yes_args ); |
| 824 | $url_no = add_query_arg( [ |
| 825 | 'wisdom_plugin' => $this->plugin_name, |
| 826 | 'wisdom_plugin_action' => 'no', |
| 827 | 'wisdom_plugin_nonce' => $nonce, |
| 828 | ] ); |
| 829 | |
| 830 | // Decide on notice text |
| 831 | if ( $this->marketing != 1 ) { |
| 832 | // Standard notice text |
| 833 | $notice_text = sprintf( __( 'Thank you for installing our %1$s. We would like to track its usage on your site. We don\'t record any sensitive data, only information regarding the WordPress environment and %1$s settings, which we will use to help us make improvements to the %1$s. Tracking is completely optional.', 'pods' ), $this->what_am_i ); |
| 834 | } else { |
| 835 | // If we have option 1 for marketing, we include reference to sending product information here |
| 836 | $notice_text = sprintf( __( 'Thank you for installing our %1$s. We\'d like your permission to track its usage on your site and subscribe you to our newsletter. We won\'t record any sensitive data, only information regarding the WordPress environment and %1$s settings, which we will use to help us make improvements to the %1$s. Tracking is completely optional.', 'pods' ), $this->what_am_i ); |
| 837 | } |
| 838 | // And we allow you to filter the text anyway |
| 839 | $notice_text = apply_filters( 'wisdom_notice_text_' . esc_attr( $this->plugin_name ), $notice_text ); ?> |
| 840 | |
| 841 | <div class="notice notice-info updated put-dismiss-notice"> |
| 842 | <p><?php echo '<strong>' . esc_html( $plugin_name ) . '</strong>'; ?></p> |
| 843 | <p><?php echo esc_html( $notice_text ); ?></p> |
| 844 | <p> |
| 845 | <a href="<?php echo esc_url( $url_yes ); ?>" class="button-secondary"><?php _e( 'Allow', 'pods' ); ?></a> |
| 846 | <a href="<?php echo esc_url( $url_no ); ?>" class="button-secondary"><?php _e( 'Do Not Allow', 'pods' ); ?></a> |
| 847 | </p> |
| 848 | </div> |
| 849 | <?php |
| 850 | } |
| 851 | } |
| 852 | |
| 853 | } |
| 854 |