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 / classes / analytify-settings / actions.php

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

365 lines 14.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php // phpcs:ignore Squiz.Commenting.FileComment.Missing -- File doc comment exists
2
3 /**
4 * Analytify Settings Actions Trait
5 *
6 * This trait handles all action-related functionality for the Analytify settings.
7 * It was created to separate action processing logic from the main settings class,
8 * making the code more organized and easier to test.
9 *
10 * PURPOSE:
11 * - Processes form submissions and actions
12 * - Handles AJAX requests for settings
13 * - Manages settings updates and deletions
14 * - Provides action hooks and callbacks
15 *
16 * @package WP_Analytify
17 * @subpackage Settings
18 * @since 8.0.0
19 */
20
21 trait Analytify_Settings_Actions {
22
23 /**
24 * Enqueue media scripts for email settings.
25 *
26 * @return void
27 */
28 public function analytify_email_enqueue_media() {
29 if ( WPANALYTIFY_Utils::is_current_page( 'analytify-settings' ) ) {
30 wp_enqueue_media();
31 }
32 }
33
34 /**
35 * Enqueue admin scripts.
36 *
37 * @return void
38 */
39 public function admin_enqueue_scripts() {
40 wp_enqueue_script( 'jquery' );
41 }
42
43 /**
44 * Initialize admin settings.
45 *
46 * @return void
47 */
48 public function admin_init() {
49 global $pagenow;
50 WPANALYTIFY_Utils::handle_ga4_exceptions();
51 $current_page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading URL parameter for display purposes
52 if ( ( 'admin.php' === $pagenow && $current_page && 'analytify-settings' === $current_page ) || 'options.php' === $pagenow ) {
53 $this->set_sections( $this->get_settings_sections() );
54 $this->set_fields( $this->get_settings_fields() );
55 foreach ( $this->settings_sections as $section ) {
56 register_setting( $section['id'], $section['id'], array( $this, 'sanitize_options' ) );
57 }
58 }
59 }
60
61 /**
62 * Render settings sections and fields.
63 *
64 * @return void
65 */
66 public function rendered_settings() {
67 foreach ( $this->settings_sections as $section ) {
68 if ( false === get_option( $section['id'] ) ) {
69 add_option( $section['id'] );
70 }
71 if ( isset( $section['desc'] ) && ! empty( $section['desc'] ) ) {
72 $section['desc'] = '<div class="inside">' . $section['desc'] . '</div>';
73 $callback = call_user_func( array( $this, 'get_description' ), $section['desc'] );
74 } elseif ( isset( $section['callback'] ) ) {
75 $callback = $section['callback'];
76 } else {
77 $callback = null;
78 }
79 add_settings_section( $section['id'], '', $callback, $section['id'] );
80 }
81 foreach ( $this->settings_fields as $section => $field ) {
82 foreach ( $field as $option ) {
83 // Skip invalid options that don't have required fields.
84 if ( ! isset( $option['name'] ) || ! isset( $option['label'] ) ) {
85 continue;
86 }
87
88 $type = isset( $option['type'] ) ? $option['type'] : 'text';
89 $args = array(
90 'id' => $option['name'],
91 'label_for' => "{$section}[{$option['name']}]",
92 'desc' => isset( $option['desc'] ) ? $option['desc'] : '',
93 'name' => $option['label'],
94 'section' => $section,
95 'size' => isset( $option['size'] ) ? $option['size'] : null,
96 'options' => isset( $option['options'] ) ? $option['options'] : '',
97 'std' => isset( $option['default'] ) ? $option['default'] : '',
98 'sanitize_callback' => isset( $option['sanitize_callback'] ) ? $option['sanitize_callback'] : '',
99 'class' => isset( $option['class'] ) ? $option['class'] : '',
100 'type' => $type,
101 'tooltip' => isset( $option['tooltip'] ) ? $option['tooltip'] : true,
102 'input_format' => isset( $option['input_format'] ) ? $option['input_format'] : '',
103 'maxlength' => isset( $option['maxlength'] ) ? $option['maxlength'] : '',
104 );
105 $callback_method = 'callback_' . $type;
106 if ( method_exists( $this, $callback_method ) ) {
107 $callback = array( $this, $callback_method );
108 if ( is_callable( $callback ) ) {
109 add_settings_field( $section . '[' . $option['name'] . ']', $option['label'], $callback, $section, $section, $args );
110 }
111 }
112 }
113 }
114 }
115
116 /**
117 * Display settings tabs.
118 *
119 * @return void
120 */
121 public function show_tabs() {
122 $html = '<div class="wpa-tab-wrapper">';
123 $html .= '<ul class="analytify_nav_tab_wrapper nav-tab-wrapper">';
124
125 // Get accordion IDs to exclude from main tabs.
126 $accordion_ids = array();
127 foreach ( $this->settings_sections as $tab ) {
128 if ( isset( $tab['accordion'] ) && is_array( $tab['accordion'] ) ) {
129 foreach ( $tab['accordion'] as $accordion_item ) {
130 if ( isset( $accordion_item['id'] ) ) {
131 $accordion_ids[] = $accordion_item['id'];
132 }
133 }
134 }
135 }
136
137 foreach ( $this->settings_sections as $tab ) {
138 // Skip invalid tabs that don't have required fields.
139 if ( ! isset( $tab['id'] ) || ! isset( $tab['title'] ) ) {
140 continue;
141 }
142
143 // Skip accordion items from appearing as separate tabs.
144 // But never skip the main tracking tab itself.
145 if ( in_array( $tab['id'], $accordion_ids, true ) && 'wp-analytify-tracking' !== $tab['id'] ) {
146 continue;
147 }
148
149 if ( 'wp-analytify-tracking' === $tab['id'] ) {
150 if ( 0 !== $tab['priority'] ) {
151 $html .= '<li>';
152 $html .= '<a href="#wp-analytify-tracking" class="analytify_nav_tab" id="wp-analytify-tracking-tab">Tracking</a>';
153 $html .= '<ul class="tabs-dropdown-menu">';
154
155 // Check if accordion exists and is an array before looping.
156 if ( isset( $tab['accordion'] ) && is_array( $tab['accordion'] ) ) {
157 foreach ( $tab['accordion'] as $accordion ) {
158 // Skip invalid accordion items that don't have required fields.
159 if ( ! isset( $accordion['id'] ) || ! isset( $accordion['title'] ) ) {
160 continue;
161 }
162
163 $html .= '<li><a href="javascript:void(0)" id="' . $accordion['id'] . '" class="wp-analytify-events-tab-item">' . $accordion['title'] . '</a>';
164 if ( ! class_exists( 'WP_Analytify_Pro' ) ) {
165 $html .= '<span>Upgrade your plan to unlock Premium Reports and Tracking Modules</span>';
166 } elseif ( 'wp-analytify-events-tracking' === $accordion['id'] ) {
167 $html .= '<span>Track Links, Clicks, Affiliates and files.</span>';
168 } elseif ( 'wp-analytify-custom-dimensions' === $accordion['id'] ) {
169 $html .= '<span>Setup custom dimensions tracking in Google Analytics.</span>';
170 } elseif ( 'wp-analytify-forms-dashboard' === $accordion['id'] ) {
171 $html .= '<span>Track Forms submissions, impressions and conversions in Google Analytics.</span>';
172 } elseif ( 'analytify-google-ads-tracking' === $accordion['id'] ) {
173 $html .= '<span>Track Ads Conversions Woocommerce and EDD purchases.</span>';
174 }
175 $html .= '</li>';
176 }
177 }
178 $html .= '</ul></li>';
179 }
180 } elseif ( 0 !== $tab['priority'] ) {
181 $html .= sprintf( '<li><a href="#%1$s" class="analytify_nav_tab" id="%1$s-tab">%2$s</a></li>', esc_attr( $tab['id'] ), esc_html( $tab['title'] ) );
182 }
183 }
184 if ( ! class_exists( 'WP_Analytify_Pro' ) ) {
185 $html .= sprintf( '<a href="%1$s" class="wp-analytify-premium" target="_blank"><span class="dashicons dashicons-star-filled"></span>%2$s</a>', esc_url( analytify_get_update_link( '', '?utm_source=analytify-lite&amp;utm_medium=tab&amp;utm_campaign=pro-upgrade' ) ), esc_html( 'Upgrade to Pro for More Features' ) );
186 }
187 $html .= '</ul></div>';
188 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
189 }
190
191 /**
192 * Get description for settings section.
193 *
194 * @param mixed $desc Description text.
195 * @return mixed Description text.
196 */
197 public function get_description( $desc ) {
198 return $desc;
199 }
200
201 /**
202 * Display settings sections for a page.
203 *
204 * @param mixed $page Page identifier.
205 * @return void
206 */
207 public function do_settings_sections( $page ) {
208 global $wp_settings_sections, $wp_settings_fields;
209 if ( ! isset( $wp_settings_sections ) || ! isset( $wp_settings_sections[ $page ] ) ) {
210 return;
211 }
212 foreach ( (array) $wp_settings_sections[ $page ] as $section ) {
213 echo '<h3>' . esc_html( $section['title'] ) . "</h3>\n";
214 echo $section['callback']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Callback output is controlled
215 if ( ! isset( $wp_settings_fields ) || ! isset( $wp_settings_fields[ $page ] ) || ! isset( $wp_settings_fields[ $page ][ $section['id'] ] ) ) {
216 continue;
217 }
218 echo '<table class="form-table">';
219 do_settings_fields( $page, $section['id'] );
220 echo '</table>';
221 }
222 }
223
224 /**
225 * Display settings forms.
226 *
227 * @return void
228 */
229 public function show_forms() {
230 global $wp_settings_sections, $wp_settings_fields;
231 settings_errors();
232 $is_authenticate = get_option( 'pa_google_token' );
233 ?>
234 <div class="metabox-holder">
235 <?php
236 foreach ( $this->settings_sections as $form ) {
237 // Skip invalid forms that don't have required fields.
238 if ( ! isset( $form['id'] ) ) {
239 continue;
240 }
241
242 if ( 0 !== $form['priority'] ) {
243 ?>
244 <?php $class = ( ! $is_authenticate && ( 'wp-analytify-profile' === $form['id'] || 'wp-analytify-admin' === $form['id'] || 'wp-analytify-dashboard' === $form['id'] || 'wp-analytify-email' === $form['id'] ) ) ? 'analytify_not_authenticate' : ''; ?>
245 <div id="<?php echo esc_attr( $form['id'] ); ?>" class="group <?php echo esc_attr( $class ); ?>" style="display: none;">
246 <?php
247 if ( 'wp-analytify-authentication' === $form['id'] ) {
248 $this->callback_authentication();
249 if ( ! get_option( 'pa_google_token' ) ) {
250 ?>
251 <form method="post" action="options.php">
252 <?php
253 settings_fields( $form['id'] );
254 // Only show GA Tracking ID field when not logged in, not the toggle.
255 global $wp_settings_fields;
256 if ( isset( $wp_settings_fields['wp-analytify-authentication']['wp-analytify-authentication'] ) ) {
257 echo '<table class="form-table">';
258 foreach ( $wp_settings_fields['wp-analytify-authentication']['wp-analytify-authentication'] as $field_id => $field ) {
259 // Only show manual_ua_code field, skip the toggle.
260 if ( 'wp-analytify-authentication[manual_ua_code]' === $field_id ) {
261 ?>
262 <tr>
263 <th scope="row"><?php echo esc_html( isset( $field['title'] ) ? $field['title'] : '' ); ?></th>
264 <td>
265 <?php call_user_func( $field['callback'], $field['args'] ); ?>
266 </td>
267 </tr>
268 <?php
269 }
270 }
271 echo '</table>';
272 }
273 ?>
274 <div style="padding-left: 10px"><?php submit_button(); ?></div>
275 </form>
276 <?php
277 }
278 } elseif ( 'wp-analytify-license' === $form['id'] ) {
279 do_action( 'wp_analytify_license_tab' );
280 } elseif ( 'wp-analytify-help' === $form['id'] ) {
281 $this->callback_help();
282 } elseif ( 'wp-analytify-advanced' === $form['id'] ) {
283 ?>
284 <form method="post" action="options.php">
285 <?php
286 settings_fields( $form['id'] );
287 $this->do_settings_sections( $form['id'] );
288 ?>
289 <div style="padding-left: 10px"><?php submit_button(); ?></div>
290 </form>
291 <?php
292 } else {
293 if ( ! $is_authenticate && ( 'wp-analytify-profile' === $form['id'] || 'wp-analytify-admin' === $form['id'] || 'wp-analytify-dashboard' === $form['id'] || 'wp-analytify-email' === $form['id'] ) ) {
294 echo "<span class='analytify_need_authenticate_first'><a href='#'>You have to Authenticate the Google Analytics first.</a></span>";
295 } elseif ( 'wp-analytify-front' === $form['id'] ) {
296 echo '<div class="analytify-email-premium-overlay"><div class="analytify-email-premium-popup"><h3 class="analytify-promo-popup-heading" style="text-align:left;">Unable To Fetch Front-end Settings</h3><p class="analytify-promo-popup-paragraph analytify-error-popup-paragraph">This is deprecated and not supported in GA4</p></div></div>';
297 } elseif ( 'wp-analytify-tracking' === $form['id'] && isset( $form['accordion'] ) ) {
298 // Render Tracking accordions (promo or pro).
299 if ( class_exists( 'WP_Analytify_Pro' ) ) {
300 do_action( 'wp_analytify_tracking_accordion_pro', $form['accordion'] );
301 } else {
302 do_action( 'wp_analytify_tracking_accordion_promo', $form['accordion'] );
303 }
304 }
305 if ( 'wp-analytify-front' !== $form['id'] && 'wp-analytify-tracking' !== $form['id'] ) {
306 ?>
307 <form method="post" action="options.php">
308 <?php
309 settings_fields( $form['id'] );
310 $this->do_settings_sections( $form['id'] );
311 ?>
312 <div id='profile-save-button-wrapper' style="padding-left: 10px;">
313 <?php submit_button(); ?>
314 <div id="setup-wait-message-disabled">
315 <img src="<?php echo esc_url( ( defined( 'ANALYTIFY_PLUGIN_URL' ) ? ANALYTIFY_PLUGIN_URL : '' ) . 'assets/img/loaaader.gif' ); ?>">
316 <p>Hold on! It may take upto 2 minutes (max) while we setup GA4 tracking.</p>
317 </div>
318 </div>
319 </form>
320 <?php } ?>
321 <?php
322 if ( 'wp-analytify-email' === $form['id'] ) {
323 $this->callback_email_form();
324 }
325 ?>
326 <?php } ?>
327 </div>
328 <?php
329 }
330 }
331 ?>
332 </div>
333 <?php
334 }
335
336
337
338 /**
339 * Delete Analytify cache.
340 *
341 * @return void
342 */
343 public function analytify_delete_cache() {
344 $delete_cache_from_bar = isset( $_GET['analytify_delete_cache_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['analytify_delete_cache_nonce'] ) ), 'analytify_delete_cache' );
345 $delete_cache_from_settings = isset( $_POST['analytify_delete_cache_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['analytify_delete_cache_nonce'] ) ), 'analytify_delete_cache' );
346 if ( $delete_cache_from_bar || $delete_cache_from_settings ) {
347 // Clear GA4 dashboard transients.
348 delete_transient( 'analytify_quota_exception' );
349 global $wpdb;
350 $esc_key = '%' . $wpdb->esc_like( '_analytify_transient' ) . '%';
351 $wpdb->query( $wpdb->prepare( "DELETE FROM `{$wpdb->prefix}options` WHERE option_name LIKE %s", $esc_key ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Cache deletion requires direct query
352
353 // Clear Search Console cache.
354 delete_option( 'analytify_search_console_data' );
355
356 status_header( 200 );
357 $goback = add_query_arg( 'analytify-cache', 'true', wp_get_referer() );
358 wp_safe_redirect( $goback );
359 die();
360 }
361 }
362 }
363
364
365