PluginProbe
Analytify – Google Analytics Dashboard For WordPress (GA4 analytics tracking) / trunk
Analytify – Google Analytics Dashboard For WordPress (GA4 analytics tracking) vtrunk
9.1.2 9.1.1 9.1.0 9.0.2 9.0.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.1.0 1.1.1 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 All 153 releases
wp-analytify / inc / analytify-utilities.php

analytify-utilities.php in Analytify – Google Analytics Dashboard For WordPress (GA4 analytics tracking) trunk, at inc/analytify-utilities.php

427 lines 10.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Utilities File for Analytify Plugin
4 *
5 * This file contains all utility and helper methods including
6 * exception handling, cache management, and other helper functions.
7 *
8 * @package WP_Analytify
9 * @since 8.0.0
10 */
11
12 // Prevent direct access.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Utility Methods for Analytify_General Class
19 */
20 trait Analytify_General_Utilities {
21
22 /**
23 * Echo value to be returned in ajax response.
24 *
25 * @param boolean $response The response value to echo.
26 *
27 * @return void
28 */
29 public function end_ajax( $response = false ) {
30
31 $response = apply_filters( 'wpanalytify_before_response', $response );
32
33 // Detect if response is JSON and don't escape it (JSON must be output as-is).
34 if ( false !== $response && is_string( $response ) ) {
35 // Check if it's JSON by trying to decode it.
36 $decoded = json_decode( $response, true );
37 if ( json_last_error() === JSON_ERROR_NONE ) {
38 // It's valid JSON, set proper headers and output without HTML escaping.
39 header( 'Content-Type: application/json; charset=utf-8' );
40 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JSON output should not be escaped
41 echo $response;
42 exit;
43 }
44 }
45
46 echo ( false === $response ) ? '' : esc_html( $response );
47 exit;
48 }
49
50 /**
51 * Check ajax referer facade.
52 *
53 * @param string $action The action to check.
54 *
55 * @return void
56 */
57 public function check_ajax_referer( $action ) {
58
59 $result = check_ajax_referer( $action, 'nonce', false );
60
61 if ( false === $result ) {
62 $return = array(
63 'wpanalytify_error' => 1,
64 // translators: %s is the action name.
65 'body' => sprintf( __( 'Invalid nonce for: %s', 'wp-analytify' ), $action ),
66 );
67 $this->end_ajax( wp_json_encode( $return ) );
68 }
69
70 $cap = ( is_multisite() ) ? 'manage_network_options' : 'export';
71 $cap = apply_filters( 'wpanalytify_ajax_cap', $cap );
72
73 if ( ! current_user_can( $cap ) ) {
74 $return = array(
75 'wpanalytify_error' => 1,
76 // translators: %s is the action name.
77 'body' => sprintf( __( 'Access denied for: %s', 'wp-analytify' ), $action ),
78 );
79 $this->end_ajax( wp_json_encode( $return ) );
80 }
81 }
82
83 /**
84 * Returns the function name that called the function using this function.
85 *
86 * @return string
87 */
88 public function get_caller_function() {
89 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_debug_backtrace -- debug_backtrace is used here to retrieve the actual calling function name, not for debugging purposes.
90 $backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 3 );
91 $caller = '';
92
93 if ( isset( $backtrace[2]['function'] ) ) {
94 $caller = $backtrace[2]['function'];
95 }
96
97 return $caller;
98 }
99
100 /**
101 * Set $this->state_data from $_POST, potentially un-slashed and sanitized.
102 *
103 * @param array $key_rules An optional associative array of expected keys and their sanitization rule(s).
104 * @param string $context The method that is specifying the sanitization rules. Defaults to calling method.
105 *
106 * @since 2.0
107 * @return array
108 */
109 public function set_post_data( $key_rules = array(), $context = '' ) {
110
111 if ( defined( 'DOING_WPANALYTIFY_TESTS' ) ) {
112 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- This is a utility function for internal use
113 $this->state_data = $_POST;
114 } elseif ( is_null( $this->state_data ) ) {
115 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- This is a utility function for internal use
116 $this->state_data = WPANALYTIFY_Utils::safe_wp_unslash( $_POST );
117 } else {
118 return $this->state_data;
119 }
120
121 // From this point on we're handling data originating from $_POST, so original $key_rules apply.
122 global $wpanalytify_key_rules;
123
124 if ( empty( $key_rules ) && ! empty( $wpanalytify_key_rules ) ) {
125 $key_rules = $wpanalytify_key_rules;
126 }
127
128 // Sanitize the new state data.
129 if ( ! empty( $key_rules ) ) {
130 $wpanalytify_key_rules = $key_rules;
131
132 $context = empty( $context ) ? $this->get_caller_function() : trim( $context );
133 $this->state_data = WPANALYTIFY_Sanitize::sanitize_data( $this->state_data, $key_rules, $context );
134
135 if ( false === $this->state_data ) {
136 exit;
137 }
138 }
139
140 return $this->state_data;
141 }
142
143 /**
144 * Create no records markup.
145 *
146 * @return void
147 */
148 public function no_records() {
149 ?>
150
151 <div class="analytify-stats-error-msg">
152 <div class="wpb-error-box">
153 <span class="blk">
154 <span class="line"></span>
155 <span class="dot"></span>
156 </span>
157 <span class="information-txt"><?php esc_html_e( 'No Activity During This Period.', 'wp-analytify' ); ?></span>
158 </div>
159 </div>
160
161 <?php
162 }
163
164 /**
165 * Get Exception value.
166 *
167 * @since 2.1.22
168 */
169 public function get_exception() {
170 return $this->exception;
171 }
172
173 /**
174 * Set Exception value.
175 *
176 * @param mixed $exception The exception to set.
177 * @since 2.1.22
178 */
179 public function set_exception( $exception ) {
180 $this->exception = $exception;
181 }
182
183 /**
184 * Get ga4 Exception value.
185 *
186 * @since 5.0.0
187 */
188 public function get_ga4_exception() {
189 return $this->ga4_exception;
190 }
191
192 /**
193 * Set Exception value.
194 *
195 * @param mixed $exception The exception to set.
196 * @since 5.0.0
197 */
198 public function set_ga4_exception( $exception ) {
199 $this->ga4_exception = $exception;
200 }
201
202 /**
203 * Generate the Error box.
204 *
205 * @param string $message The error message to display.
206 * @since 2.1.23
207 */
208 protected function show_error_box( $message ) {
209 $error = '<div class="analytify-stats-error-msg">
210 <div class="wpb-error-box">
211 <span class="blk">
212 <span class="line"></span>
213 <span class="dot"></span>
214 </span>
215 <span class="information-txt">'
216 . $message .
217 '</span>
218 </div>
219 </div>';
220
221 return $error;
222 }
223
224 /**
225 * If error, return cache result else return error.
226 *
227 * @param mixed $exception The exception to handle.
228 * @param mixed $cache_result The cached result to return if available.
229 * @since 2.1.23
230 */
231 public function tackle_exception( $exception, $cache_result ) {
232
233 if ( $cache_result ) {
234 return $cache_result;
235 }
236
237 echo wp_kses_post( $this->show_error_box( $exception ) );
238 }
239
240 /**
241 * Set Cache time for Stats.
242 *
243 * @version 5.0.4
244 * @since 2.2.1
245 */
246 public function set_cache_time() {
247 $this->cache_timeout = $this->settings->get_option( 'delete_dashboard_cache', 'wp-analytify-dashboard', 'off' ) === 'on' ? apply_filters( 'analytify_stats_cache_time', 60 * 60 * 10 ) : apply_filters( 'analytify_stats_cache_time', 60 * 60 * 24 );
248 }
249
250 /**
251 * Get Cache time for Stats.
252 *
253 * @version 5.0.4
254 *
255 * @since 2.2.1
256 */
257 public function get_cache_time() {
258 return $this->cache_timeout;
259 }
260
261 /**
262 * Check the active/deactive state of addon/moudle.
263 *
264 * @param string $slug Slug of addon./moudle.
265 * @return string $addon_state: active or deactive
266 * @version 9.0.0
267 */
268 public function analytify_module_state( $slug ) {
269
270 $wp_analytify = $GLOBALS['WP_ANALYTIFY'];
271 $addon_state = '';
272
273 $pro_inner = array(
274 'detail-realtime',
275 'detail-demographic',
276 'search-terms',
277 'page-speed',
278 'search-console-report',
279 'video-tracking',
280 );
281 $pro_addon = array(
282 'wp-analytify-woocommerce',
283 'wp-analytify-goals',
284 'wp-analytify-authors',
285 'wp-analytify-learndash',
286 'wp-analytify-edd',
287 'wp-analytify-forms',
288 'wp-analytify-campaigns',
289 'wp-analytify-lifterlms',
290 'wp-analytify-pmpro',
291 );
292 $pro_features = array(
293 'custom-dimensions',
294 'events-tracking',
295 );
296
297 if ( in_array( $slug, $pro_features, true ) ) {
298 $analytify_modules = get_option( 'wp_analytify_modules' );
299
300 if ( 'active' === $analytify_modules[ $slug ]['status'] ) {
301 $addon_state = 'active';
302 } else {
303 $addon_state = 'deactive';
304 }
305 } elseif ( in_array( $slug, $pro_addon, true ) || in_array( $slug, $pro_inner, true ) ) {
306 if ( in_array( $slug, $pro_inner, true ) ) {
307 $slug = 'wp-analytify-pro';
308 }
309
310 if ( $wp_analytify->addon_is_active( $slug ) ) {
311 $addon_state = 'active';
312 } else {
313 $addon_state = 'deactive';
314 }
315 }
316
317 return $addon_state;
318 }
319
320 /**
321 * Check if external addon is active.
322 *
323 * @param string $slug Slug of addon.
324 *
325 * @return bool $addon_active
326 * @version 9.0.0
327 */
328 public function addon_is_active( $slug ) {
329
330 $addon_active = false;
331
332 switch ( $slug ) {
333 case 'wp-analytify':
334 if ( class_exists( 'Analytify_General' ) ) {
335 $addon_active = true;
336 }
337 break;
338
339 case 'wp-analytify-goals':
340 if ( class_exists( 'WP_Analytify_Goals' ) ) {
341 $addon_active = true;
342 }
343 break;
344
345 case 'wp-analytify-woocommerce':
346 if ( class_exists( 'WP_Analytify_WooCommerce' ) || class_exists( 'WP_Analytify_WooCommerce_Addon' ) ) {
347 $addon_active = true;
348 }
349 break;
350
351 case 'wp-analytify-campaigns':
352 if ( class_exists( 'ANALYTIFY_PRO_CAMPAIGNS' ) ) {
353 $addon_active = true;
354 }
355 break;
356
357 case 'wp-analytify-authors':
358 if ( class_exists( 'Analytify_Authors' ) || class_exists( 'Analytify_Addon_Authors' ) ) {
359 $addon_active = true;
360 }
361 break;
362
363 case 'wp-analytify-edd':
364 if ( class_exists( 'WP_Analytify_Edd' ) || class_exists( 'WP_Analytify_Edd_Addon' ) ) {
365 $addon_active = true;
366 }
367 break;
368
369 case 'wp-analytify-pmpro':
370 if ( class_exists( 'WP_Analytify_Pmpro_Addon' ) ) {
371 $addon_active = true;
372 }
373 break;
374
375 case 'wp-analytify-forms':
376 if ( class_exists( 'Analytify_Forms' ) || class_exists( 'Analytify_Addon_Forms' ) ) {
377 $addon_active = true;
378 }
379 break;
380
381 case 'wp-analytify-pro':
382 if ( class_exists( 'WP_Analytify_Pro_Base' ) ) {
383 $addon_active = true;
384 }
385 break;
386
387 case 'wp-analytify-lifterlms':
388 if ( class_exists( 'WP_Analytify_LifterLMS_Addon' ) ) {
389 $addon_active = true;
390 }
391 break;
392
393 case 'wp-analytify-learndash':
394 if ( class_exists( 'WP_Analytify_LearnDash_Addon' ) || class_exists( 'WP_Analytify_LearnDash' ) ) {
395 $addon_active = true;
396 }
397 break;
398
399 default:
400 $addon_active = false;
401 break;
402 }
403
404 return $addon_active;
405 }
406
407 /**
408 * Handle caching of GA4 reports data and store it as transient
409 *
410 * @since 7.0.0
411 * @param string $cache_key The cache key to use.
412 * @param mixed $data The data to cache.
413 * @param string $name The report name.
414 * @param bool $should_cache Whether to cache the data.
415 * @return bool|void
416 */
417 private function analytify_handle_report_cache( $cache_key, $data, $name, $should_cache = true ) {
418 // Don't cache if caching is disabled or for specific reports.
419 if ( ! $should_cache || 'show-worldmap-front' === $name ) {
420 return false;
421 }
422
423 // Set the cache with the configured timeout.
424 set_transient( $cache_key, $data, $this->get_cache_time() );
425 }
426 }
427