PluginProbe
Analytics Insights – Google Analytics Dashboard for WordPress / trunk
Analytics Insights – Google Analytics Dashboard for WordPress vtrunk
6.3.6 6.3.7 6.3.8 6.3.9 trunk 5.4.1 5.4.2 5.4.2.1 5.4.3 5.4.4 5.4.5 5.4.6 5.4.7 5.5.2 5.5.3 5.5.4 5.5.5 5.5.6 5.6 5.6.1 5.6.2 5.6.3 5.6.4 5.6.5 5.6.6 All 61 releases
analytics-insights / tools / tools.php

tools.php in Analytics Insights – Google Analytics Dashboard for WordPress trunk, at tools/tools.php

493 lines 17.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Author: Alin Marcu
4 * Author URI: https://deconf.com
5 * Copyright 2013 Alin Marcu
6 * License: GPLv2 or later
7 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
8 */
9 // Exit if accessed directly
10 if ( ! defined( 'ABSPATH' ) )
11 exit();
12 if ( ! class_exists( 'AIWP_Tools' ) ) {
13
14 class AIWP_Tools {
15
16 public static function get_countrycodes() {
17 include 'iso3166.php';
18 return $country_codes;
19 }
20
21 public static function guess_default_domain( $profiles, $index = 3 ) {
22 $domain = get_option( 'siteurl' );
23 $domain = str_ireplace( array( 'http://', 'https://' ), '', $domain );
24 if ( ! empty( $profiles ) ) {
25 foreach ( $profiles as $items ) {
26 if ( strpos( $items[$index], $domain ) ) {
27 return $items[1];
28 }
29 }
30 return $profiles[0][1];
31 } else {
32 return '';
33 }
34 }
35
36 public static function get_selected_profile( $profiles, $profile ) {
37 if ( ! empty( $profiles ) ) {
38 foreach ( $profiles as $item ) {
39 if ( isset( $item[1] ) && $item[1] == $profile ) {
40 return $item;
41 }
42 }
43 }
44 }
45
46 public static function get_root_domain() {
47 $url = site_url();
48 $root = explode( '/', $url );
49 preg_match( '/(?P<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i', str_ireplace( 'www', '', isset( $root[2] ) ? $root[2] : $url ), $root );
50 if ( isset( $root['domain'] ) ) {
51 return $root['domain'];
52 } else {
53 return '';
54 }
55 }
56
57 public static function strip_protocol( $domain ) {
58 return str_replace( array( "https://", "http://", " " ), "", $domain );
59 }
60
61 public static function colourVariator( $colour, $per ) {
62 $colour = substr( $colour, 1 );
63 $rgb = '';
64 $per = $per / 100 * 255;
65 if ( $per < 0 ) {
66 // Darker
67 $per = abs( $per );
68 for ( $x = 0; $x < 3; $x++ ) {
69 $c = hexdec( substr( $colour, ( 2 * $x ), 2 ) ) - $per;
70 $c = ( $c < 0 ) ? 0 : dechex( (int) $c );
71 $rgb .= ( strlen( $c ) < 2 ) ? '0' . $c : $c;
72 }
73 } else {
74 // Lighter
75 for ( $x = 0; $x < 3; $x++ ) {
76 $c = hexdec( substr( $colour, ( 2 * $x ), 2 ) ) + $per;
77 $c = ( $c > 255 ) ? 'ff' : dechex( (int) $c );
78 $rgb .= ( strlen( $c ) < 2 ) ? '0' . $c : $c;
79 }
80 }
81 return '#' . $rgb;
82 }
83
84 public static function variations( $base ) {
85 $variations[] = $base;
86 $variations[] = self::colourVariator( $base, - 10 );
87 $variations[] = self::colourVariator( $base, + 10 );
88 $variations[] = self::colourVariator( $base, + 20 );
89 $variations[] = self::colourVariator( $base, - 20 );
90 $variations[] = self::colourVariator( $base, + 30 );
91 $variations[] = self::colourVariator( $base, - 30 );
92 return $variations;
93 }
94
95 public static function check_roles( $access_level, $tracking = false ) {
96 if ( is_user_logged_in() && isset( $access_level ) ) {
97 $current_user = wp_get_current_user();
98 $roles = (array) $current_user->roles;
99 if ( ( current_user_can( 'manage_options' ) ) && ! $tracking ) {
100 return true;
101 }
102 if ( count( array_intersect( $roles, $access_level ) ) > 0 ) {
103 return true;
104 } else {
105 return false;
106 }
107 }
108 }
109
110 public static function unset_cookie( $name ) {
111 $name = 'aiwp_wg_' . $name;
112 setcookie( $name, '', time() - 3600, '/' );
113 $name = 'aiwp_ir_' . $name;
114 setcookie( $name, '', time() - 3600, '/' );
115 }
116
117 /**
118 * Cache Helper function. I don't use transients because cleanup plugins can break their functionality
119 * @param string $name
120 * @param mixed $value
121 * @param number $expiration
122 */
123 public static function set_cache( $name, $value, $expiration = 0 ) {
124 update_option( '_aiwp_cache_' . $name, $value, 'no' );
125 if ( $expiration ) {
126 update_option( '_aiwp_cache_timeout_' . $name, time() + (int) $expiration, 'no' );
127 } else {
128 update_option( '_aiwp_cache_timeout_' . $name, time() + 7 * 24 * 3600, 'no' );
129 }
130 }
131
132 /**
133 * Cache Helper function. I don't use transients because cleanup plugins can break their functionality
134 * @param string $name
135 * @param mixed $value
136 * @param number $expiration
137 */
138 public static function delete_cache( $name ) {
139 delete_option( '_aiwp_cache_' . $name );
140 delete_option( '_aiwp_cache_timeout_' . $name );
141 }
142
143 /**
144 * Cache Helper function. I don't use transients because cleanup plugins can break their functionality
145 * @param string $name
146 * @param mixed $value
147 * @param number $expiration
148 */
149 public static function get_cache( $name ) {
150 $value = get_option( '_aiwp_cache_' . $name );
151 $expires = get_option( '_aiwp_cache_timeout_' . $name );
152 if ( false === $value || ! isset( $value ) || ! isset( $expires ) ) {
153 return false;
154 }
155 if ( $expires < time() ) {
156 delete_option( '_aiwp_cache_' . $name );
157 delete_option( '_aiwp_cache_timeout_' . $name );
158 return false;
159 } else {
160 return $value;
161 }
162 }
163
164 /**
165 * Cache Helper function. I don't use transients because cleanup plugins can break their functionality
166 */
167 public static function clear_cache() {
168 global $wpdb;
169 $sqlquery = $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE '%%aiwp_cache_%%'" );
170 }
171
172 public static function delete_expired_cache() {
173 global $wpdb, $wp_version;
174 if ( wp_using_ext_object_cache() ) {
175 return;
176 }
177 if ( version_compare( $wp_version, '4.0.0', '>=' ) ) {
178 $wpdb->query( $wpdb->prepare( "DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b
179 WHERE a.option_name LIKE %s
180 AND a.option_name NOT LIKE %s
181 AND b.option_name = CONCAT( '_aiwp_cache_timeout_', SUBSTRING( a.option_name, 13 ) )
182 AND b.option_value < %d", $wpdb->esc_like( '_aiwp_cache_' ) . '%', $wpdb->esc_like( '_aiwp_cache_timeout_' ) . '%', time() ) );
183 if ( ! is_multisite() ) {
184 // Single site stores site transients in the options table.
185 $wpdb->query( $wpdb->prepare( "DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b
186 WHERE a.option_name LIKE %s
187 AND a.option_name NOT LIKE %s
188 AND b.option_name = CONCAT( '_site_aiwp_cache_timeout_', SUBSTRING( a.option_name, 18 ) )
189 AND b.option_value < %d", $wpdb->esc_like( '_site_aiwp_cache_' ) . '%', $wpdb->esc_like( '_site_aiwp_cache_timeout_' ) . '%', time() ) );
190 } elseif ( is_multisite() && is_main_site() && is_main_network() ) {
191 // Multisite stores site transients in the sitemeta table.
192 $wpdb->query( $wpdb->prepare( "DELETE a, b FROM {$wpdb->sitemeta} a, {$wpdb->sitemeta} b
193 WHERE a.meta_key LIKE %s
194 AND a.meta_key NOT LIKE %s
195 AND b.meta_key = CONCAT( '_site_aiwp_cache_timeout_', SUBSTRING( a.meta_key, 18 ) )
196 AND b.meta_value < %d", $wpdb->esc_like( '_site_aiwp_cache_' ) . '%', $wpdb->esc_like( '_site_aiwp_cache_timeout_' ) . '%', time() ) );
197 }
198 } else {
199 $wpdb->query( $wpdb->prepare( "DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b
200 WHERE a.option_name LIKE %s
201 AND a.option_name NOT LIKE %s
202 AND b.option_name = CONCAT( '_aiwp_cache_timeout_', SUBSTRING( a.option_name, 13 ) )
203 AND b.option_value < %d", like_escape( '_aiwp_cache_' ) . '%', like_escape( '_aiwp_cache_timeout_' ) . '%', time() ) );
204 if ( ! is_multisite() ) {
205 // Single site stores site transients in the options table.
206 $wpdb->query( $wpdb->prepare( "DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b
207 WHERE a.option_name LIKE %s
208 AND a.option_name NOT LIKE %s
209 AND b.option_name = CONCAT( '_site_aiwp_cache_timeout_', SUBSTRING( a.option_name, 18 ) )
210 AND b.option_value < %d", like_escape( '_site_aiwp_cache_' ) . '%', like_escape( '_site_aiwp_cache_timeout_' ) . '%', time() ) );
211 } elseif ( is_multisite() && is_main_site() && is_main_network() ) {
212 // Multisite stores site transients in the sitemeta table.
213 $wpdb->query( $wpdb->prepare( "DELETE a, b FROM {$wpdb->sitemeta} a, {$wpdb->sitemeta} b
214 WHERE a.meta_key LIKE %s
215 AND a.meta_key NOT LIKE %s
216 AND b.meta_key = CONCAT( '_site_aiwp_cache_timeout_', SUBSTRING( a.meta_key, 18 ) )
217 AND b.meta_value < %d", like_escape( '_site_aiwp_cache_' ) . '%', like_escape( '_site_aiwp_cache_timeout_' ) . '%', time() ) );
218 }
219 }
220 }
221
222 public static function get_sites( $args ) { // Use wp_get_sites() if WP version is lower than 4.6.0
223 global $wp_version;
224 if ( version_compare( $wp_version, '4.6.0', '<' ) ) {
225 return wp_get_sites( $args );
226 } else {
227 foreach ( get_sites( $args ) as $blog ) {
228 $blogs[] = (array) $blog; // Convert WP_Site object to array
229 }
230 return $blogs;
231 }
232 }
233
234 /**
235 * Loads a view file
236 *
237 * $data parameter will be available in the template file as $data['value']
238 *
239 * @param string $template - Template file to load
240 * @param array $data - data to pass along to the template
241 * @return boolean - If template file was found
242 **/
243 public static function load_view( $path, $data = array(), $globalsitetag = 0 ) {
244 if ( file_exists( AIWP_DIR . $path ) ) {
245 require ( AIWP_DIR . $path );
246 return true;
247 }
248 return false;
249 }
250
251 public static function doing_it_wrong( $function, $message, $version ) {
252 if ( WP_DEBUG && apply_filters( 'doing_it_wrong_trigger_error', true ) ) {
253 if ( is_null( $version ) ) {
254 $version = '';
255 } else {
256 /* translators: %s: version number */
257 $version = sprintf( __( 'This message was added in version %s.', 'analytics-insights' ), $version );
258 }
259 /* translators: Developer debugging message. 1: PHP function name, 2: Explanatory message, 3: Version information message */
260 trigger_error( sprintf( __( '%1$s was called <strong>incorrectly</strong>. %2$s %3$s', 'analytics-insights' ), $function, $message, $version ) );
261 }
262 }
263
264 public static function get_dom_from_content( $content ) {
265 $libxml_previous_state = libxml_use_internal_errors( true );
266 if ( class_exists( 'DOMDocument' ) ) {
267 $dom = new DOMDocument();
268 $result = $dom->loadHTML( '<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body>' . $content . '</body></html>' );
269 libxml_clear_errors();
270 libxml_use_internal_errors( $libxml_previous_state );
271 if ( ! $result ) {
272 return false;
273 }
274 return $dom;
275 } else {
276 self::set_error( __( 'DOM is disabled or libxml PHP extension is missing. Contact your hosting provider. Automatic tracking of events for AMP pages is not possible.', 'analytics-insights' ), 24 * 60 * 60 );
277 return false;
278 }
279 }
280
281 public static function get_content_from_dom( $dom ) {
282 $out = '';
283 $body = $dom->getElementsByTagName( 'body' )->item( 0 );
284 foreach ( $body->childNodes as $node ) {
285 $out .= $dom->saveXML( $node );
286 }
287 return $out;
288 }
289
290 public static function array_keys_rename( $options, $keys ) {
291 foreach ( $keys as $key => $newkey ) {
292 if ( isset( $options[$key] ) ) {
293 $options[$newkey] = $options[$key];
294 unset( $options[$key] );
295 }
296 }
297 return $options;
298 }
299
300 public static function set_error( $e, $timeout, $ajax = false ) {
301 if ( $ajax ) {
302 self::set_cache( 'ajax_errors', esc_html( print_r( $e, true ) ), $timeout );
303 } else {
304 if ( is_object( $e ) ) {
305 if ( method_exists( $e, 'get_error_code' ) && method_exists( $e, 'get_error_message' ) ) {
306 $error_code = $e->get_error_code();
307 if ( 500 == $error_code || 503 == $error_code ) {
308 $timeout = 60;
309 }
310 self::set_cache( 'api_errors', array( $e->get_error_code(), $e->get_error_message(), $e->get_error_data() ), $timeout );
311 } else {
312 self::set_cache( 'api_errors', array( 600, array(), esc_html( print_r( $e, true ) ) ), $timeout );
313 }
314 } else if ( is_array( $e ) ) {
315 self::set_cache( 'api_errors', array( 601, array(), esc_html( print_r( $e, true ) ) ), $timeout );
316 } else {
317 self::set_cache( 'api_errors', array( 602, array(), esc_html( print_r( $e, true ) ) ), $timeout );
318 }
319 // Count Errors until midnight
320 $midnight = strtotime( "tomorrow 00:00:00" ); // UTC midnight
321 $midnight = $midnight + 8 * 3600; // UTC 8 AM
322 $tomidnight = $midnight - time();
323 $errors_count = self::get_cache( 'errors_count' );
324 $errors_count = (int) $errors_count + 1;
325 self::set_cache( 'errors_count', $errors_count, $tomidnight );
326 }
327 }
328
329 public static function anonymize_options( $options ) {
330 global $wp_version;
331 $options['wp_version'] = $wp_version;
332 $options['aiwp_version'] = AIWP_CURRENT_VERSION;
333 if ( $options['token'] && ( ! WP_DEBUG || ( is_multisite() && ! current_user_can( 'manage_network_options' ) ) ) ) {
334 $options['token'] = 'HIDDEN';
335 } else {
336 $options['token'] = (array) $options['token'];
337 unset( $options['token']['challenge'] );
338 }
339 if ( $options['client_secret'] ) {
340 $options['client_secret'] = 'HIDDEN';
341 }
342 return $options;
343 }
344
345 public static function system_info() {
346 $info = '';
347 // Server Software
348 $server_soft = "-";
349 if ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
350 $server_soft = $_SERVER['SERVER_SOFTWARE'];
351 }
352 $info .= 'Server Info: ' . sanitize_text_field( $server_soft ) . "\n";
353 // PHP version
354 if ( defined( 'PHP_VERSION' ) ) {
355 $info .= 'PHP Version: ' . PHP_VERSION . "\n";
356 } else if ( defined( 'HHVM_VERSION' ) ) {
357 $info .= 'HHVM Version: ' . HHVM_VERSION . "\n";
358 } else {
359 $info .= 'Other Version: ' . '-' . "\n";
360 }
361 // cURL Info
362 if ( function_exists( 'curl_version' ) && function_exists( 'curl_exec' ) ) {
363 $curl_version = curl_version();
364 if ( ! empty( $curl_version ) ) {
365 $curl_ver = $curl_version['version'] . " " . $curl_version['ssl_version'];
366 } else {
367 $curl_ver = '-';
368 }
369 } else {
370 $curl_ver = '-';
371 }
372 $info .= 'cURL Info: ' . $curl_ver . "\n";
373 // Gzip
374 if ( is_callable( 'gzopen' ) ) {
375 $gzip = true;
376 } else {
377 $gzip = false;
378 }
379 $gzip_status = ( $gzip ) ? 'Yes' : 'No';
380 $info .= 'Gzip: ' . $gzip_status . "\n";
381 return $info;
382 }
383
384 /**
385 * Follows the SCRIPT_DEBUG settings
386 * @param string $script
387 * @return string
388 */
389 public static function script_debug_suffix() {
390 if ( defined( 'SCRIPT_DEBUG' ) and SCRIPT_DEBUG ) {
391 return '';
392 } else {
393 return '.min';
394 }
395 }
396
397 /**
398 * Dimensions and metric mapping from GA3 to GA4
399 * @param string $value
400 * @return string
401 */
402 public static function ga3_ga4_mapping( $value ) {
403 $value = str_replace( 'ga:', '', $value );
404 $list = [ 'users' => 'totalUsers', 'sessionDuration' => 'userEngagementDuration', 'fullReferrer' => 'pageReferrer', 'source' => 'sessionSource', 'medium' => 'sessionMedium', 'dataSource' => 'platform',
405 // 'pagePath' => 'pagePathPlusQueryString',
406 'pageviews' => 'screenPageViews', 'pageviewsPerSession' => 'screenPageViewsPerSession', 'timeOnPage' => 'userEngagementDuration', 'channelGrouping' => 'sessionDefaultChannelGrouping', 'dayOfWeekName' => 'dayOfWeek', 'visitBounceRate' => 'bounceRate', 'organicSearches' => 'engagedSessions', 'socialNetwork' => 'language', 'visitorType' => 'newVsReturning', 'uniquePageviews' => 'sessions' ];
407 if ( isset( $list[$value] ) ) {
408 return $list[$value];
409 } else {
410 return $value;
411 }
412 }
413
414 public static function secondstohms( $value ) {
415 $value = (float) $value;
416 $hours = floor( $value / 3600 );
417 $hours = $hours < 10 ? '0' . $hours : (string) $hours;
418 $minutes = floor( (int) ( $value / 60 ) % 60 );
419 $minutes = $minutes < 10 ? '0' . $minutes : (string) $minutes;
420 $seconds = floor( (int)$value % 60 );
421 $seconds = $seconds < 10 ? '0' . $seconds : (string) $seconds;
422 return $hours . ':' . $minutes . ':' . $seconds;
423 }
424
425 public static function is_amp() {
426 if ( is_singular( 'web-story' ) ) {
427 return true;
428 }
429 return function_exists( 'is_amp_endpoint' ) && is_amp_endpoint();
430 }
431
432 public function generate_random( $length = 10 ) {
433 $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
434 $charactersLength = strlen( $characters );
435 $randomString = '';
436 for ( $i = 0; $i < $length; $i++ ) {
437 $randomString .= $characters[random_int( 0, $charactersLength - 1 )];
438 }
439 return $randomString;
440 }
441
442 public static function report_errors() {
443 if ( AIWP_Tools::get_cache( 'api_errors' ) ) {
444 $info = AIWP_Tools::system_info();
445 $info .= 'AIWP Version: ' . AIWP_CURRENT_VERSION;
446 $sep = "\n---------------------------\n";
447 $error_report = $sep . print_r( AIWP_Tools::get_cache( 'api_errors' ), true );
448 $error_report .= $sep . AIWP_Tools::get_cache( 'errors_count' );
449 $error_report .= $sep . $info;
450 $error_report = urldecode( $error_report );
451 $url = AIWP_ENDPOINT_URL . 'aiwp-report.php';
452 /* @formatter:off */
453 $response = wp_remote_post( $url, array(
454 'method' => 'POST',
455 'timeout' => 45,
456 'redirection' => 5,
457 'httpversion' => '1.0',
458 'blocking' => true,
459 'headers' => array(),
460 'body' => array( 'error_report' => esc_html( $error_report ) ),
461 'cookies' => array()
462 )
463 );
464 /* @formatter:off */
465 }
466 }
467
468 /** Keeps compatibility with WP < 5.3.0
469 *
470 * @return string
471 */
472 public static function timezone_string() {
473 $timezone_string = get_option( 'timezone_string' );
474
475 if ( $timezone_string ) {
476 return $timezone_string;
477 }
478
479 $offset = (float) get_option( 'gmt_offset' );
480 $hours = (int) $offset;
481 $minutes = ( $offset - $hours );
482
483 $sign = ( $offset < 0 ) ? '-' : '+';
484 $abs_hour = abs( $hours );
485 $abs_mins = abs( $minutes * 60 );
486 $tz_offset = sprintf( '%s%02d:%02d', $sign, $abs_hour, $abs_mins );
487
488 return $tz_offset;
489 }
490
491 }
492 }
493