PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 1.9
Independent Analytics – WordPress Analytics Plugin v1.9
2.15.5 2.15.4 2.15.3 2.15.2 2.15.1 2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / inc / independent_analytics.php
independent-analytics / inc Last commit date
ajax 4 years ago databases 4 years ago migrations 4 years ago models 4 years ago queries 4 years ago utils 4 years ago chart.php 4 years ago chart_geo.php 4 years ago db.php 4 years ago filters.php 4 years ago freemius.php 4 years ago independent_analytics.php 4 years ago known_referrers.php 4 years ago quick_stats.php 4 years ago rest_api.php 4 years ago settings.php 4 years ago table.php 4 years ago table_geo.php 4 years ago table_referrers.php 4 years ago table_views.php 4 years ago track_resource_changes.php 4 years ago
independent_analytics.php
357 lines
1 <?php
2
3 namespace IAWP;
4
5 class Independent_Analytics
6 {
7 use Singleton;
8
9 // This is where we attach functions to WP hooks
10 private function __construct()
11 {
12 $this->rest_api = new REST_API();
13 $this->settings = new Settings();
14 new Delete_Data_AJAX();
15 new Filters_AJAX();
16 new Export_Geo_AJAX();
17 new Export_Referrers_AJAX();
18 new Export_Views_AJAX();
19 new Migration_Status_AJAX();
20 new Track_Resource_Changes();
21
22 add_action('admin_menu', [$this, 'add_settings_page']);
23 add_action('admin_enqueue_scripts', [$this, 'enqueue_scripts']);
24 add_filter('plugin_action_links_independent-analytics/iawp.php', [$this, 'plugin_action_links']);
25 add_filter('admin_footer_text', [$this, 'ip_db_attribution'], 1, 11);
26 IAWP_FS()->add_filter('connect_message_on_update', [$this, 'filter_connect_message_on_update'], 10, 6);
27 IAWP_FS()->add_filter('connect_message', [$this, 'filter_connect_message_on_update'], 10, 6);
28 }
29
30 // Text domain is used for i18n
31 public function load_textdomain()
32 {
33 load_plugin_textdomain('iawp', false, path_to('/languages'));
34 }
35
36 // Settings page where the analytics will appear
37 public function add_settings_page()
38 {
39 add_menu_page(
40 'Independent Analytics',
41 esc_html__('Analytics', 'iawp'),
42 'manage_options',
43 'independent-analytics',
44 [$this, 'settings_page_markup'],
45 'dashicons-analytics',
46 3
47 );
48 }
49
50 private function get_current_tab()
51 {
52 $valid_tabs = ['views', 'referrers', 'geo', 'settings'];
53 $default_tab = $valid_tabs[0];
54 $tab = array_key_exists('tab', $_GET) ? sanitize_text_field($_GET['tab']) : false;
55 $is_valid = array_search($tab, $valid_tabs) != false;
56
57 if (!$tab || !$is_valid) {
58 $tab = $default_tab;
59 }
60
61 return $tab;
62 }
63
64 public function settings_page_markup()
65 {
66 $classes = get_option('iawp_dark_mode') ? 'iawp-parent dark-mode' : 'iawp-parent';
67
68 // check user capabilities
69 if (!$this->min_permission_level('admin')) {
70 return;
71 }
72
73 // Show migration message if needed
74 if (Migration::is_migrating()) {
75 ?>
76 <div id="iawp-parent" class="<?php echo esc_attr($classes); ?>">
77 <?php echo IAWP()->templates()->render('layout/header', ['show_review' => false]) ?>
78 <?php echo IAWP()->templates()->render('migration_running') ?>
79 </div>
80 <?php
81 return;
82 }
83
84 $tab = $this->get_current_tab(); ?>
85 <div id="iawp-parent" class="<?php echo esc_attr($classes); ?>">
86 <?php echo IAWP()->templates()->render('layout/header') ?>
87 <nav class="menu">
88 <a href="?page=independent-analytics"
89 class="menu-item link-dark <?php if ($tab === 'views'): ?>active<?php endif; ?>">
90 <?php esc_html_e('Views', 'iawp'); ?>
91 </a>
92 <a href="?page=independent-analytics&tab=referrers"
93 class="menu-item link-dark <?php if ($tab === 'referrers'): ?>active<?php endif; ?>">
94 <?php esc_html_e('Referrers', 'iawp'); ?>
95 </a>
96 <a href="?page=independent-analytics&tab=geo"
97 class="menu-item link-dark <?php if ($tab === 'geo'): ?>active<?php endif; ?>">
98 <?php esc_html_e('Geographic', 'iawp'); ?>
99 </a>
100 <a href="?page=independent-analytics&tab=settings"
101 class="menu-item link-dark <?php if ($tab === 'settings'): ?>active<?php endif; ?>">
102 <?php esc_html_e('Settings', 'iawp'); ?>
103 </a>
104 </nav>
105 <div class="tab-content"><?php
106 if ($tab == 'views') {
107 $table = new Table_Views();
108 $views = new Views(Views::RESOURCES);
109 $stats = new Quick_Stats($views);
110 $chart = new Chart($views);
111 $this->interface($table, $stats, $chart);
112 } elseif ($tab == 'referrers') {
113 $table = new Table_Referrers();
114 $views = new Views(Views::RESOURCES);
115 $stats = new Quick_Stats($views);
116 $chart = new Chart($views);
117 $this->interface($table, $stats, $chart);
118 } elseif ($tab == 'geo') {
119 $table = new Table_Geo();
120 $views = new Views(Views::GEO);
121 $stats = new Quick_Stats($views);
122 $geos = new Geos(null, null, false, null);
123 $chart = new Chart_Geo($geos);
124 $this->interface($table, $stats, $chart);
125 } elseif ($tab == 'settings') {
126 echo '<div id="iawp-dashboard" class="iawp-dashboard">';
127 Security::html($this->settings->render_settings());
128 echo '</div>';
129 } ?>
130 </div>
131 <div id="loading-icon" class="loading-icon"><img
132 src="<?php echo esc_url(url_to('img/loading.svg')) ?>"/>
133 </div>
134 <button id="scroll-to-top" class="scroll-to-top"><span
135 class="dashicons dashicons-arrow-up-alt"></span>
136 </button>
137 </div>
138 <?php
139 }
140
141 public function interface($table, $stats, $chart)
142 {
143 ?>
144 <div id="iawp-dashboard"
145 class="iawp-dashboard"
146 data-controller="report"
147 data-report-relative-range-id-value="LAST_THIRTY"
148 data-report-exact-start-value=""
149 data-report-exact-end-value=""
150 data-report-columns-value="<?php esc_attr_e(Security::json_encode($table->default_columns())) ?>"
151 >
152 <?php echo Security::html($table->output_toolbar($table->columns())); ?>
153 <?php echo $stats->get_html(); ?>
154 <?php echo $chart->get_html(); ?>
155 <?php echo Security::html($table->get_table_markup()); ?>
156 </div>
157 <?php
158 }
159
160 public function enqueue_scripts($hook)
161 {
162 if ($hook == 'toplevel_page_independent-analytics') {
163 $tab = $this->get_current_tab();
164
165 wp_register_style('iawp-style', url_to('dist/styles/style.css'), [], IAWP_VERSION);
166 wp_enqueue_style('iawp-style');
167
168 wp_register_script('iawp-js', url_to('dist/js/index.js'), [], IAWP_VERSION);
169 wp_enqueue_script('iawp-js');
170 wp_add_inline_script('iawp-js', 'const IAWP_DELETE_DATA_NONCE = ' . json_encode(wp_create_nonce('iawp_delete_data')), 'before');
171
172 if ($tab === 'views' || $tab === 'referrers' || $tab === 'geo') {
173 wp_register_script('iawp-data-table', url_to('dist/js/data-table.js'), [], IAWP_VERSION);
174 wp_enqueue_script('iawp-data-table');
175 wp_add_inline_script('iawp-data-table', 'const IAWP_AJAX = ' . json_encode([
176 'filter_nonce' => wp_create_nonce('iawp_filter'),
177 ]), 'before');
178 } elseif ($tab == 'settings') {
179 wp_register_script('iawp-settings', url_to('dist/js/settings.js'), [], IAWP_VERSION);
180 wp_enqueue_script('iawp-settings');
181 wp_add_inline_script('iawp-settings', 'const IAWP_AJAX = ' . json_encode([
182 'export_views_nonce' => wp_create_nonce('iawp_export_views'),
183 'export_referrers_nonce' => wp_create_nonce('iawp_export_referrers'),
184 'export_geo_nonce' => wp_create_nonce('iawp_export_geo'),
185 ]), 'before');
186 }
187 }
188 }
189
190 public function default_date_range()
191 {
192 $user_timezone = new \DateTimeZone(Timezone::local_offset());
193 $end = (new \DateTime(null, $user_timezone))->setTime(0, 0, 0);
194 $start = clone $end;
195 $start->modify('-29 days');
196
197 return [$start, $end];
198 }
199
200 public function previous_range(DateTime $start, DateTime $end)
201 {
202 $diff = $start->diff($end)->days + 1;
203 $prev_start = clone $start;
204 $prev_end = clone $end;
205
206 return [$prev_start->modify("-$diff days"), $prev_end->modify("-$diff days")];
207 }
208
209 // Returns bool based on minimum capability requirements
210 public function min_permission_level($role = 'subscriber')
211 {
212 if ($role == 'contributor') {
213 return current_user_can('edit_posts');
214 } elseif ($role == 'author') {
215 return current_user_can('publish_posts');
216 } elseif ($role == 'editor') {
217 return current_user_can('edit_others_posts');
218 } elseif ($role == 'admin') {
219 return current_user_can('manage_options');
220 } else {
221 return false;
222 }
223 }
224
225 public function get_full_permalink($id, $post_type)
226 {
227 // 0-> http://website.com/04/%postname%/
228 // 1-> example-post-title
229 $permalink_data = get_sample_permalink($id);
230 $permalink_base = $permalink_data[0];
231 if ($post_type == 'post') {
232 $permalink_base = trailingslashit(str_replace('%postname%', '', $permalink_base));
233 } else {
234 $permalink_base = trailingslashit(str_replace('%pagename%', '', $permalink_base));
235 }
236
237 $slug = $permalink_data[1];
238
239 $permalink = [
240 'base' => $permalink_base,
241 'slug' => $slug,
242 ];
243
244 return $permalink;
245 }
246
247 /* WP uses $default when get_option() is empty, but it also saves empty fields
248 ** as empty strings, meaning the return value can be "" instead of the default. This is
249 ** a defensive function that guarantees we get the proper default when the setting is empty. */
250 public function get_option($name, $default)
251 {
252 $option = get_option($name, $default);
253
254 return $option === '' ? $default : $option;
255 }
256
257 public function templates()
258 {
259 return new League\Plates\Engine(path_to('templates'));
260 }
261
262 public function get_users_can_write()
263 {
264 $roles = [];
265 foreach (wp_roles()->roles as $role_name => $role_obj) {
266 if (!empty($role_obj['capabilities']['edit_posts'])) {
267 $roles[] = $role_name;
268 }
269 }
270
271 $users = get_users(['role__in' => $roles]);
272
273 return $users;
274 }
275
276 public function get_custom_types(bool $tax = false)
277 {
278 $args = [
279 'public' => true,
280 '_builtin' => false,
281 ];
282 if ($tax) {
283 return get_taxonomies($args);
284 } else {
285 return get_post_types($args);
286 }
287 }
288
289 public function filter_connect_message_on_update(
290 $message,
291 $user_first_name,
292 $product_title,
293 $user_login,
294 $site_link,
295 $freemius_link
296 ) {
297 // Add the heading HTML.
298 $plugin_name = 'Independent Analytics';
299 $title = '<h3>' . sprintf(esc_html__('We hope you love %1$s', 'iawp'), $plugin_name) . '</h3>';
300 $html = '';
301
302 // Add the introduction HTML.
303 $html .= '<p>';
304 $html .= sprintf(esc_html__('Hi, %1$s! This is an invitation to help the %2$s community. ', 'iawp'), $user_first_name, $plugin_name);
305 $html .= '<strong>';
306 $html .= sprintf(esc_html__('If you opt-in, some data about your usage of %2$s will be shared with us', 'iawp'), $user_first_name, $plugin_name);
307 $html .= '</strong>';
308 $html .= sprintf(esc_html__(' so we can improve %2$s. We will also share some helpful info on using the plugin so you can get the most out of your sites analytics.', 'iawp'), $user_first_name, $plugin_name);
309 $html .= '</p>';
310
311 $html .= '<p>';
312 $html .= sprintf(esc_html__('And if you skip this, that\'s okay! %1$s will still work just fine.', 'iawp'), $plugin_name);
313 $html .= '</p>';
314
315 // Add the "Powered by" HTML.
316 $html .= '<div class="iawp-powered-by-freemius">' . esc_html__('Powered by Freemius', 'iawp') . '</div>';
317
318 return $title . $html;
319 }
320
321 public function plugin_action_links($links)
322 {
323 // Build the URL
324 $url = add_query_arg('page', 'independent-analytics', admin_url('admin.php'));
325
326 // Create the link
327 $settings_link = '<a class="calendar-link" href="' . esc_url($url) . '">' . esc_html__('Analytics Dashboard', 'iawp') . '</a>';
328
329 // Add the link to the start of the array
330 array_unshift($links, $settings_link);
331
332 return $links;
333 }
334
335 public function set_time_limit($limit = 0)
336 {
337 if (
338 !function_exists('set_time_limit')
339 && false !== strpos(ini_get('disable_functions'), 'set_time_limit')
340 && ini_get('safe_mode')
341 ) {
342 return false;
343 }
344
345 return @set_time_limit($limit);
346 }
347
348 public function ip_db_attribution($text)
349 {
350 if ($this->get_current_tab() === 'geo') {
351 $text = $text . ' ' . esc_html_x('Geolocation data powered by', 'Following text is a noun: DB-IP', 'iawp') . ' ' . '<a href="https://db-ip.com" class="geo-message" target="_blank">DB-IP</a>.';
352 }
353
354 return $text;
355 }
356 }
357