PluginProbe ʕ •ᴥ•ʔ
Starter Templates – AI-Powered Templates for Elementor & Gutenberg / 2.6.11
Starter Templates – AI-Powered Templates for Elementor & Gutenberg v2.6.11
4.6.1 4.6.0 4.5.4 4.5.3 2.3.6 2.3.7 2.3.8 2.3.9 2.4.0 2.5.0 2.5.1 2.6.0 2.6.1 2.6.10 2.6.11 2.6.12 2.6.13 2.6.14 2.6.15 2.6.16 2.6.17 2.6.18 2.6.19 2.6.2 2.6.20 2.6.21 2.6.22 2.6.3 2.6.4 2.6.5 2.6.6 2.6.7 2.6.8 2.6.9 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 3.0.0 3.0.1 3.0.10 3.0.11 3.0.12 3.0.13 3.0.14 3.0.15 3.0.16 3.0.17 3.0.18 3.0.19 3.0.2 3.0.20 3.0.21 3.0.22 3.0.23 3.0.24 3.0.25 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 3.1.19 3.1.2 3.1.20 3.1.21 3.1.22 3.1.23 3.1.24 3.1.25 3.1.26 3.1.27 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.3.0 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.5.6 3.5.7 4.0.0 4.0.1 4.0.10 4.0.11 4.0.12 4.0.13 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.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.7 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.3.0 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.3.8 4.3.9 4.4.0 4.4.1 4.4.10 4.4.11 4.4.12 4.4.13 4.4.14 4.4.16 4.4.17 4.4.18 4.4.19 4.4.2 4.4.20 4.4.21 4.4.22 4.4.23 4.4.24 trunk 4.4.25 0.4.4.0 4.4.26 0.4.4.15 4.4.27 1.0.0 4.4.28 1.0.1 4.4.29 1.0.10 4.4.3 1.0.11 4.4.30 1.0.12 4.4.31 1.0.13 4.4.32 1.0.14 4.4.33 1.0.2 4.4.34 1.0.3 4.4.35 1.0.4 4.4.36 1.0.5 4.4.37 1.0.6 4.4.38 1.0.7 4.4.39 1.0.8 4.4.4 1.0.9 4.4.40 1.1.0 4.4.41 1.1.1 4.4.42 1.1.2 4.4.43 1.1.3 4.4.44 1.1.4 4.4.45 1.1.5 4.4.46 1.1.6 4.4.47 1.1.7 4.4.48 1.1.8 4.4.49 1.1.9 4.4.5 1.2.0 4.4.50 1.2.1 4.4.51 1.2.10 4.4.52 1.2.11 4.4.6 1.2.12 4.4.7 1.2.13 4.4.8 1.2.14 4.4.9 1.2.15 4.5.0 1.2.2 4.5.1 1.2.3 4.5.2 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.10 1.3.11 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.19 1.3.2 1.3.20 1.3.21 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 2.0.0 2.0.1 2.0.2 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.3.5
astra-sites / admin / bsf-analytics / class-bsf-analytics.php
astra-sites / admin / bsf-analytics Last commit date
assets 5 years ago class-bsf-analytics-loader.php 5 years ago class-bsf-analytics-stats.php 5 years ago class-bsf-analytics.php 5 years ago version.json 5 years ago
class-bsf-analytics.php
509 lines
1 <?php
2 /**
3 * BSF analytics class file.
4 *
5 * @version 1.0.0
6 *
7 * @package bsf-analytics
8 */
9
10 if ( ! defined( 'ABSPATH' ) ) {
11 exit; // Exit if accessed directly.
12 }
13
14 if ( ! class_exists( 'BSF_Analytics' ) ) {
15
16 /**
17 * BSF analytics
18 */
19 class BSF_Analytics {
20
21 /**
22 * Member Variable
23 *
24 * @var array Entities data.
25 */
26 private $entities;
27
28 /**
29 * Member Variable
30 *
31 * @var string Usage tracking document URL
32 */
33 public $usage_doc_link = 'https://store.brainstormforce.com/usage-tracking/?utm_source=wp_dashboard&utm_medium=general_settings&utm_campaign=usage_tracking';
34
35 /**
36 * Setup actions, load files.
37 *
38 * @param array $args entity data for analytics.
39 * @param string $analytics_path directory path to analytics library.
40 * @param float $analytics_version analytics library version.
41 * @since 1.0.0
42 */
43 public function __construct( $args, $analytics_path, $analytics_version ) {
44
45 // Bail when no analytics entities are registered.
46 if ( empty( $args ) ) {
47 return;
48 }
49
50 $this->entities = $args;
51
52 define( 'BSF_ANALYTICS_VERSION', $analytics_version );
53 define( 'BSF_ANALYTICS_URI', $this->get_analytics_url( $analytics_path ) );
54
55 add_action( 'admin_init', array( $this, 'handle_optin_optout' ) );
56 add_action( 'admin_notices', array( $this, 'option_notice' ) );
57 add_action( 'init', array( $this, 'maybe_track_analytics' ), 99 );
58
59 $this->set_actions();
60
61 add_action( 'admin_init', array( $this, 'register_usage_tracking_setting' ) );
62
63 $this->includes();
64 }
65
66 /**
67 * Setup actions for admin notice style and analytics cron event.
68 *
69 * @since 1.0.4
70 */
71 public function set_actions() {
72
73 foreach ( $this->entities as $key => $data ) {
74 add_action( 'astra_notice_before_markup_' . $key . '-optin-notice', array( $this, 'enqueue_assets' ) );
75 add_action( 'update_option_' . $key . '_analytics_optin', array( $this, 'update_analytics_option_callback' ), 10, 3 );
76 add_action( 'add_option_' . $key . '_analytics_optin', array( $this, 'add_analytics_option_callback' ), 10, 2 );
77 }
78 }
79
80 /**
81 * BSF Analytics URL
82 *
83 * @param string $analytics_path directory path to analytics library.
84 * @return String URL of bsf-analytics directory.
85 * @since 1.0.0
86 */
87 public function get_analytics_url( $analytics_path ) {
88
89 $content_dir_path = wp_normalize_path( WP_CONTENT_DIR );
90
91 $analytics_path = wp_normalize_path( $analytics_path );
92
93 return str_replace( $content_dir_path, content_url(), $analytics_path );
94 }
95
96 /**
97 * Get API URL for sending analytics.
98 *
99 * @return string API URL.
100 * @since 1.0.0
101 */
102 private function get_api_url() {
103 return defined( 'BSF_API_URL' ) ? BSF_API_URL : 'https://support.brainstormforce.com/';
104 }
105
106 /**
107 * Enqueue Scripts.
108 *
109 * @since 1.0.0
110 * @return void
111 */
112 public function enqueue_assets() {
113
114 /**
115 * Load unminified if SCRIPT_DEBUG is true.
116 *
117 * Directory and Extensions.
118 */
119 $dir_name = ( SCRIPT_DEBUG ) ? 'unminified' : 'minified';
120 $file_rtl = ( is_rtl() ) ? '-rtl' : '';
121 $css_ext = ( SCRIPT_DEBUG ) ? '.css' : '.min.css';
122
123 $css_uri = BSF_ANALYTICS_URI . '/assets/css/' . $dir_name . '/style' . $file_rtl . $css_ext;
124
125 wp_enqueue_style( 'bsf-analytics-admin-style', $css_uri, false, BSF_ANALYTICS_VERSION, 'all' );
126 }
127
128 /**
129 * Send analytics API call.
130 *
131 * @since 1.0.0
132 */
133 public function send() {
134 wp_remote_post(
135 $this->get_api_url() . 'wp-json/bsf-core/v1/analytics/',
136 array(
137 'body' => BSF_Analytics_Stats::instance()->get_stats(),
138 'timeout' => 5,
139 'blocking' => false,
140 )
141 );
142 }
143
144 /**
145 * Check if usage tracking is enabled.
146 *
147 * @return bool
148 * @since 1.0.0
149 */
150 public function is_tracking_enabled() {
151
152 foreach ( $this->entities as $key => $data ) {
153
154 $is_enabled = get_site_option( $key . '_analytics_optin' ) === 'yes' ? true : false;
155 $is_enabled = $this->is_white_label_enabled( $key ) ? false : $is_enabled;
156
157 if ( apply_filters( $key . '_tracking_enabled', $is_enabled ) ) {
158 return true;
159 }
160 }
161
162 return false;
163 }
164
165 /**
166 * Check if WHITE label is enabled for BSF products.
167 *
168 * @param string $source source of analytics.
169 * @return bool
170 * @since 1.0.0
171 */
172 public function is_white_label_enabled( $source ) {
173
174 $options = apply_filters( $source . '_white_label_options', array() );
175 $is_enabled = false;
176
177 if ( is_array( $options ) ) {
178 foreach ( $options as $option ) {
179 if ( true === $option ) {
180 $is_enabled = true;
181 break;
182 }
183 }
184 }
185
186 return $is_enabled;
187 }
188
189 /**
190 * Display admin notice for usage tracking.
191 *
192 * @since 1.0.0
193 */
194 public function option_notice() {
195
196 if ( ! current_user_can( 'manage_options' ) ) {
197 return;
198 }
199
200 foreach ( $this->entities as $key => $data ) {
201
202 $time_to_display = isset( $data['time_to_display'] ) ? $data['time_to_display'] : '+24 hours';
203 $usage_doc_link = isset( $data['usage_doc_link'] ) ? $data['usage_doc_link'] : $this->usage_doc_link;
204
205 // Don't display the notice if tracking is disabled or White Label is enabled for any of our plugins.
206 if ( false !== get_site_option( $key . '_analytics_optin', false ) || $this->is_white_label_enabled( $key ) ) {
207 continue;
208 }
209
210 // Show tracker consent notice after 24 hours from installed time.
211 if ( strtotime( $time_to_display, $this->get_analytics_install_time( $key ) ) > time() ) {
212 continue;
213 }
214
215 /* translators: %s product name */
216 $notice_string = __( 'Want to help make <strong>%1s</strong> even more awesome? Allow us to collect non-sensitive diagnostic data and usage information. ', 'astra-sites' );
217
218 if ( is_multisite() ) {
219 $notice_string .= __( 'This will be applicable for all sites from the network.', 'astra-sites' );
220 }
221
222 $language_dir = is_rtl() ? 'rtl' : 'ltr';
223
224 Astra_Notices::add_notice(
225 array(
226 'id' => $key . '-optin-notice',
227 'type' => '',
228 'message' => sprintf(
229 '<div class="notice-content">
230 <div class="notice-heading">
231 %1$s
232 </div>
233 <div class="astra-notices-container">
234 <a href="%2$s" class="astra-notices button-primary">
235 %3$s
236 </a>
237 <a href="%4$s" data-repeat-notice-after="%5$s" class="astra-notices button-secondary">
238 %6$s
239 </a>
240 </div>
241 </div>',
242 /* translators: %s usage doc link */
243 sprintf( $notice_string . '<span dir="%2s"><a href="%3s" target="_blank" rel="noreferrer noopener">%4s</a><span>', esc_html( $data['product_name'] ), $language_dir, esc_url( $usage_doc_link ), __( ' Know More.', 'astra-sites' ) ),
244 add_query_arg(
245 array(
246 $key . '_analytics_optin' => 'yes',
247 $key . '_analytics_nonce' => wp_create_nonce( $key . '_analytics_optin' ),
248 'bsf_analytics_source' => $key,
249 )
250 ),
251 __( 'Yes! Allow it', 'astra-sites' ),
252 add_query_arg(
253 array(
254 $key . '_analytics_optin' => 'no',
255 $key . '_analytics_nonce' => wp_create_nonce( $key . '_analytics_optin' ),
256 'bsf_analytics_source' => $key,
257 )
258 ),
259 MONTH_IN_SECONDS,
260 __( 'No Thanks', 'astra-sites' )
261 ),
262 'show_if' => true,
263 'repeat-notice-after' => false,
264 'priority' => 18,
265 'display-with-other-notices' => true,
266 )
267 );
268 }
269 }
270
271 /**
272 * Process usage tracking opt out.
273 *
274 * @since 1.0.0
275 */
276 public function handle_optin_optout() {
277
278 if ( ! current_user_can( 'manage_options' ) ) {
279 return;
280 }
281
282 $source = isset( $_GET['bsf_analytics_source'] ) ? sanitize_text_field( wp_unslash( $_GET['bsf_analytics_source'] ) ) : '';
283
284 if ( ! isset( $_GET[ $source . '_analytics_nonce' ] ) ) {
285 return;
286 }
287
288 if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET[ $source . '_analytics_nonce' ] ) ), $source . '_analytics_optin' ) ) {
289 return;
290 }
291
292 $optin_status = isset( $_GET[ $source . '_analytics_optin' ] ) ? sanitize_text_field( wp_unslash( $_GET[ $source . '_analytics_optin' ] ) ) : '';
293
294 if ( 'yes' === $optin_status ) {
295 $this->optin( $source );
296 } elseif ( 'no' === $optin_status ) {
297 $this->optout( $source );
298 }
299
300 wp_safe_redirect(
301 remove_query_arg(
302 array(
303 $source . '_analytics_optin',
304 $source . '_analytics_nonce',
305 'bsf_analytics_source',
306 )
307 )
308 );
309 }
310
311 /**
312 * Opt in to usage tracking.
313 *
314 * @param string $source source of analytics.
315 * @since 1.0.0
316 */
317 private function optin( $source ) {
318 update_site_option( $source . '_analytics_optin', 'yes' );
319 }
320
321 /**
322 * Opt out to usage tracking.
323 *
324 * @param string $source source of analytics.
325 * @since 1.0.0
326 */
327 private function optout( $source ) {
328 update_site_option( $source . '_analytics_optin', 'no' );
329 }
330
331 /**
332 * Load analytics stat class.
333 *
334 * @since 1.0.0
335 */
336 private function includes() {
337 require_once __DIR__ . '/class-bsf-analytics-stats.php';
338 }
339
340 /**
341 * Register usage tracking option in General settings page.
342 *
343 * @since 1.0.0
344 */
345 public function register_usage_tracking_setting() {
346
347 foreach ( $this->entities as $key => $data ) {
348
349 if ( ! apply_filters( $key . '_tracking_enabled', true ) || $this->is_white_label_enabled( $key ) ) {
350 return;
351 }
352
353 $usage_doc_link = isset( $data['usage_doc_link'] ) ? $data['usage_doc_link'] : $this->usage_doc_link;
354 $author = isset( $data['author'] ) ? $data['author'] : 'Brainstorm Force';
355
356 register_setting(
357 'general', // Options group.
358 $key . '_analytics_optin', // Option name/database.
359 array( 'sanitize_callback' => array( $this, 'sanitize_option' ) ) // sanitize callback function.
360 );
361
362 add_settings_field(
363 $key . '-analytics-optin', // Field ID.
364 __( 'Usage Tracking', 'astra-sites' ), // Field title.
365 array( $this, 'render_settings_field_html' ), // Field callback function.
366 'general',
367 'default', // Settings page slug.
368 array(
369 'type' => 'checkbox',
370 'title' => $author,
371 'name' => $key . '_analytics_optin',
372 'label_for' => $key . '-analytics-optin',
373 'id' => $key . '-analytics-optin',
374 'usage_doc_link' => $usage_doc_link,
375 )
376 );
377 }
378 }
379
380 /**
381 * Sanitize Callback Function
382 *
383 * @param bool $input Option value.
384 * @since 1.0.0
385 */
386 public function sanitize_option( $input ) {
387
388 if ( ! $input || 'no' === $input ) {
389 return 'no';
390 }
391
392 return 'yes';
393 }
394
395 /**
396 * Print settings field HTML.
397 *
398 * @param array $args arguments to field.
399 * @since 1.0.0
400 */
401 public function render_settings_field_html( $args ) {
402 ?>
403 <fieldset>
404 <label for="<?php echo esc_attr( $args['label_for'] ); ?>">
405 <input id="<?php echo esc_attr( $args['id'] ); ?>" type="checkbox" value="1" name="<?php echo esc_attr( $args['name'] ); ?>" <?php checked( get_site_option( $args['name'], 'no' ), 'yes' ); ?>>
406 <?php
407 /* translators: %s Product title */
408 echo esc_html( sprintf( __( 'Allow %s products to track non-sensitive usage tracking data.', 'astra-sites' ), $args['title'] ) );// phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText
409
410 if ( is_multisite() ) {
411 esc_html_e( ' This will be applicable for all sites from the network.', 'astra-sites' );
412 }
413 ?>
414 </label>
415 <?php
416 echo wp_kses_post( sprintf( '<a href="%1s" target="_blank" rel="noreferrer noopener">%2s</a>', esc_url( $args['usage_doc_link'] ), __( 'Learn More.', 'astra-sites' ) ) );
417 ?>
418 </fieldset>
419 <?php
420 }
421
422 /**
423 * Set analytics installed time in option.
424 *
425 * @param string $source source of analytics.
426 * @return string $time analytics installed time.
427 * @since 1.0.0
428 */
429 private function get_analytics_install_time( $source ) {
430
431 $time = get_site_option( $source . '_analytics_installed_time' );
432
433 if ( ! $time ) {
434 $time = time();
435 update_site_option( $source . '_analytics_installed_time', time() );
436 }
437
438 return $time;
439 }
440
441 /**
442 * Schedule/unschedule cron event on updation of option.
443 *
444 * @param string $old_value old value of option.
445 * @param string $value value of option.
446 * @param string $option Option name.
447 * @since 1.0.0
448 */
449 public function update_analytics_option_callback( $old_value, $value, $option ) {
450 if ( is_multisite() ) {
451 $this->add_option_to_network( $option, $value );
452 }
453 }
454
455 /**
456 * Analytics option add callback.
457 *
458 * @param string $option Option name.
459 * @param string $value value of option.
460 * @since 1.0.0
461 */
462 public function add_analytics_option_callback( $option, $value ) {
463 if ( is_multisite() ) {
464 $this->add_option_to_network( $option, $value );
465 }
466 }
467
468 /**
469 * Send analaytics track event if tracking is enabled.
470 *
471 * @since 1.0.0
472 */
473 public function maybe_track_analytics() {
474
475 if ( ! $this->is_tracking_enabled() ) {
476 return;
477 }
478
479 $analytics_track = get_site_transient( 'bsf_analytics_track' );
480
481 // If the last data sent is 2 days old i.e. transient is expired.
482 if ( ! $analytics_track ) {
483 $this->send();
484 set_site_transient( 'bsf_analytics_track', true, 2 * DAY_IN_SECONDS );
485 }
486 }
487
488 /**
489 * Save analytics option to network.
490 *
491 * @param string $option name of option.
492 * @param string $value value of option.
493 * @since 1.0.0
494 */
495 public function add_option_to_network( $option, $value ) {
496
497 // If action coming from general settings page.
498 if ( isset( $_POST['option_page'] ) && 'general' === $_POST['option_page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
499
500 if ( get_site_option( $option ) ) {
501 update_site_option( $option, $value );
502 } else {
503 add_site_option( $option, $value );
504 }
505 }
506 }
507 }
508 }
509