PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 1.7
Independent Analytics – WordPress Analytics Plugin v1.7
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 / iawp.php
independent-analytics Last commit date
dist 4 years ago freemius 4 years ago img 4 years ago inc 4 years ago languages 4 years ago templates 4 years ago vendor 4 years ago iawp.php 4 years ago readme.txt 4 years ago
iawp.php
436 lines
1 <?php
2 /**
3 * Plugin Name: Independent Analytics
4 * Plugin URI: https://independentwp.com/
5 * Description: User-friendly website analytics built for WordPress
6 * Version: 1.7
7 * Requires at least: 5.5
8 * Tested up to: 6.0
9 * Requires PHP: 7.3.29
10 * Author: Independent Analytics
11 * Author URI: https://independentwp.com/
12 * License: GPL v2 or later
13 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
14 * Text Domain: iawp
15 * Domain Path: /languages
16 */
17
18 namespace IAWP;
19
20 require_once dirname(__FILE__) . '/vendor/scoper-autoload.php';
21
22 if (!function_exists('ia_fs')) {
23 // Create a helper function for easy SDK access.
24 function ia_fs()
25 {
26 global $ia_fs;
27
28 if (!isset($ia_fs)) {
29 // Include Freemius SDK.
30 require_once dirname(__FILE__) . '/freemius/start.php';
31
32 $ia_fs = fs_dynamic_init([
33 'id' => '9944',
34 'slug' => 'independent-analytics',
35 'type' => 'plugin',
36 'public_key' => 'pk_c228acaa28759b55d58766b1076d4',
37 'is_premium' => false,
38 'has_addons' => false,
39 'has_paid_plans' => false,
40 'menu' => [
41 'slug' => 'independent-analytics',
42 ],
43 ]);
44 }
45
46 return $ia_fs;
47 }
48
49 // Init Freemius.
50 ia_fs();
51 // Signal that SDK was initiated.
52 do_action('ia_fs_loaded');
53 }
54
55 if (!class_exists('Independent_Analytics')) {
56 class Independent_Analytics
57 {
58 // This enforces singleton behavior
59 public static function instance()
60 {
61 static $instance = null;
62 if ($instance === null) {
63 $instance = new self();
64 }
65
66 return $instance;
67 }
68
69 // This is where we attach functions to WP hooks
70 private function __construct()
71 {
72 $this->__setup_constants();
73 $this->__includes();
74
75 $this->db = new DB(IAWP_VERSION);
76 $this->rest_api = new REST_API();
77 $this->chart = new Chart();
78 $this->settings = new Settings();
79 new Filters_Ajax();
80 new Settings_AJAX();
81 new Delete_Data_Ajax();
82 new Track_Resource_Changes();
83
84 add_action('admin_menu', [$this, 'add_settings_page']);
85 add_action('admin_enqueue_scripts', [$this, 'enqueue_scripts']);
86 add_action('plugins_loaded', [$this, 'update_db'], 99);
87 add_filter('plugin_action_links_independent-analytics/iawp.php', [$this, 'plugin_action_links']);
88 ia_fs()->add_filter('connect_message_on_update', [$this, 'filter_connect_message_on_update'], 10, 6);
89 ia_fs()->add_filter('connect_message', [$this, 'filter_connect_message_on_update'], 10, 6);
90 }
91
92 private function __setup_constants()
93 {
94 // Plugin Folder Path
95 if (!defined('IAWP_DIR')) {
96 define('IAWP_DIR', plugin_dir_path(__FILE__));
97 }
98 // Plugin Folder URL
99 if (!defined('IAWP_URL')) {
100 define('IAWP_URL', plugin_dir_url(__FILE__));
101 }
102 // Plugin Root File
103 if (!defined('IAWP_FILE')) {
104 define('IAWP_FILE', __FILE__);
105 }
106 // Plugin version
107 if (!defined('IAWP_VERSION')) {
108 define('IAWP_VERSION', '1.7');
109 }
110 }
111
112 private function __includes()
113 {
114 require_once IAWP_DIR . 'inc/db.php';
115 require_once IAWP_DIR . 'inc/rest_api.php';
116 require_once IAWP_DIR . 'inc/table.php';
117 require_once IAWP_DIR . 'inc/table_referrers.php';
118 require_once IAWP_DIR . 'inc/table_views.php';
119 require_once IAWP_DIR . 'inc/chart.php';
120 require_once IAWP_DIR . 'inc/filters.php';
121 require_once IAWP_DIR . 'inc/filters_ajax.php';
122 require_once IAWP_DIR . 'inc/delete_data_ajax.php';
123 require_once IAWP_DIR . 'inc/track_resource_changes.php';
124 require_once IAWP_DIR . 'inc/settings.php';
125 require_once IAWP_DIR . 'inc/settings_ajax.php';
126 require_once IAWP_DIR . 'inc/utils/array_to_csv.php';
127 require_once IAWP_DIR . 'inc/utils/date_format.php';
128 require_once IAWP_DIR . 'inc/utils/request.php';
129 require_once IAWP_DIR . 'inc/utils/relative_dates.php';
130 require_once IAWP_DIR . 'inc/utils/security.php';
131 require_once IAWP_DIR . 'inc/utils/timezone.php';
132 require_once IAWP_DIR . 'inc/queries/range_query.php';
133 require_once IAWP_DIR . 'inc/queries/views.php';
134 require_once IAWP_DIR . 'inc/queries/referrers.php';
135 require_once IAWP_DIR . 'inc/queries/resources.php';
136 require_once IAWP_DIR . 'inc/models/referrer.php';
137 require_once IAWP_DIR . 'inc/models/page.php';
138 require_once IAWP_DIR . 'inc/models/page_author_archive.php';
139 require_once IAWP_DIR . 'inc/models/page_date_archive.php';
140 require_once IAWP_DIR . 'inc/models/page_home.php';
141 require_once IAWP_DIR . 'inc/models/page_not_found.php';
142 require_once IAWP_DIR . 'inc/models/page_post_type_archive.php';
143 require_once IAWP_DIR . 'inc/models/page_search.php';
144 require_once IAWP_DIR . 'inc/models/page_singular.php';
145 require_once IAWP_DIR . 'inc/models/page_term_archive.php';
146 }
147
148 // Check this to run data migrations on plugins_loaded
149 public function update_db()
150 {
151 $this->db->create_or_migrate_database();
152 }
153
154 // Text domain is used for i18n
155 public function load_textdomain()
156 {
157 load_plugin_textdomain('iawp', false, IAWP_DIR . '/languages');
158 }
159
160 // Settings page where the analytics will appear
161 public function add_settings_page()
162 {
163 add_menu_page(
164 'Independent Analytics',
165 esc_html__('Analytics', 'iawp'),
166 'manage_options',
167 'independent-analytics',
168 [$this, 'settings_page_markup'],
169 'dashicons-analytics',
170 3
171 );
172 }
173
174 private function get_current_tab()
175 {
176 $valid_tabs = ['views', 'referrers', 'settings'];
177 $default_tab = $valid_tabs[0];
178 $tab = array_key_exists('tab', $_GET) ? sanitize_text_field($_GET['tab']) : false;
179 $is_valid = array_search($tab, $valid_tabs) != false;
180
181 if (!$tab || !$is_valid) {
182 $tab = $default_tab;
183 }
184
185 return $tab;
186 }
187
188 public function settings_page_markup()
189 {
190 // check user capabilities
191 if (!$this->min_permission_level('admin')) {
192 return;
193 }
194 $classes = get_option('iawp_dark_mode') ? 'iawp-parent dark-mode' : 'iawp-parent';
195 $tab = $this->get_current_tab(); ?>
196 <div id="iawp-parent" class="<?php echo esc_attr($classes); ?>">
197 <div class="header">
198 <div class="logo"><img src="<?php echo esc_url(IAWP_URL) . 'img/logo.png' ?>"/></div>
199 <div class="kb">
200 <a href="https://wordpress.org/support/plugin/independent-analytics/reviews/" class="iawp-button text review" target="_blank">
201 <span><?php esc_html_e('Leave us a Review', 'iawp'); ?></span>
202 <span class="dashicons dashicons-star-filled"></span>
203 </a>
204 <a href="https://independentwp.com/knowledgebase/" class="iawp-button purple" target="_blank">
205 <span><?php esc_html_e('Knowledge Base', 'iawp'); ?></span>
206 <span class="dashicons dashicons-external"></span>
207 </a>
208 </div>
209 </div>
210 <nav class="menu">
211 <a href="?page=independent-analytics"
212 class="menu-item link-dark <?php if ($tab === 'views'): ?>active<?php endif; ?>">
213 <?php esc_html_e('Views', 'iawp'); ?>
214 </a>
215 <a href="?page=independent-analytics&tab=referrers"
216 class="menu-item link-dark <?php if ($tab === 'referrers'): ?>active<?php endif; ?>">
217 <?php esc_html_e('Referrers', 'iawp'); ?>
218 </a>
219 <a href="?page=independent-analytics&tab=settings"
220 class="menu-item link-dark <?php if ($tab === 'settings'): ?>active<?php endif; ?>">
221 <?php esc_html_e('Settings', 'iawp'); ?>
222 </a>
223 </nav>
224 <div class="tab-content"><?php
225 $views = new Views(Views::RESOURCES);
226 if ($tab == 'views') {
227 echo $this->interface(new Table_Views(), $views);
228 } elseif ($tab == 'referrers') {
229 echo $this->interface(new Table_Referrers(), $views);
230 } elseif ($tab == 'settings') {
231 echo '<div id="iawp-dashboard" class="iawp-dashboard">';
232 Security::html($this->settings->render_settings());
233 echo '</div>';
234 } ?>
235 </div>
236 <div id="loading-icon" class="loading-icon"><img src="<?php echo esc_url(IAWP_URL) . 'img/loading.svg' ?>"/></div>
237 </div>
238 <?php
239 }
240
241 public function interface($table, $views)
242 {
243 $html = '<div id="iawp-dashboard" class="iawp-dashboard">';
244 $html .= Security::html($table->output_toolbar($table->columns()));
245 $html .= $this->chart->quick_stats($views);
246 $html .= $this->chart->output_chart($views);
247 $html .= Security::html($table->get_table_markup());
248 $html .= '</div>';
249
250 return $html;
251 }
252
253 public function enqueue_scripts($hook)
254 {
255 if ($hook == 'toplevel_page_independent-analytics') {
256 $tab = $this->get_current_tab();
257
258 wp_register_style('iawp-style', IAWP_URL . 'dist/styles/style.css', [], IAWP_VERSION);
259 wp_enqueue_style('iawp-style');
260
261 wp_register_script('iawp-js', IAWP_URL . 'dist/js/index.js', [], IAWP_VERSION);
262 wp_enqueue_script('iawp-js');
263 wp_add_inline_script('iawp-js', 'const IAWP_DELETE_DATA_NONCE = ' . json_encode(wp_create_nonce('iawp_delete_data')), 'before');
264
265 if ($tab == 'views' || $tab == 'referrers') {
266 wp_register_script('iawp-data-table', IAWP_URL . 'dist/js/data-table.js', [], IAWP_VERSION);
267 wp_enqueue_script('iawp-data-table');
268 wp_add_inline_script('iawp-data-table', 'const IAWP_AJAX = ' . json_encode([
269 'filter_nonce' => wp_create_nonce('iawp_filter'),
270 ]), 'before');
271 } elseif ($tab == 'settings') {
272 wp_register_script('iawp-settings', IAWP_URL . 'dist/js/settings.js', [], IAWP_VERSION);
273 wp_enqueue_script('iawp-settings');
274 wp_add_inline_script('iawp-settings', 'const IAWP_AJAX = ' . json_encode([
275 'export_views_nonce' => wp_create_nonce('iawp_export_views'),
276 'export_referrers_nonce' => wp_create_nonce('iawp_export_referrers'),
277 ]), 'before');
278 }
279 }
280 }
281
282 public function default_date_range()
283 {
284 $user_timezone = new \DateTimeZone(Timezone::local_offset());
285 $end = (new \DateTime(null, $user_timezone))->setTime(0, 0, 0);
286 $start = clone $end;
287 $start->modify('-29 days');
288
289 return [$start, $end];
290 }
291
292 public function previous_range(DateTime $start, DateTime $end)
293 {
294 $diff = $start->diff($end)->days + 1;
295 $prev_start = clone $start;
296 $prev_end = clone $end;
297
298 return [$prev_start->modify("-$diff days"), $prev_end->modify("-$diff days")];
299 }
300
301 // Returns bool based on minimum capability requirements
302 public function min_permission_level($role = 'subscriber')
303 {
304 if ($role == 'contributor') {
305 return current_user_can('edit_posts');
306 } elseif ($role == 'author') {
307 return current_user_can('publish_posts');
308 } elseif ($role == 'editor') {
309 return current_user_can('edit_others_posts');
310 } elseif ($role == 'admin') {
311 return current_user_can('manage_options');
312 } else {
313 return false;
314 }
315 }
316
317 public function get_full_permalink($id, $post_type)
318 {
319 // 0-> http://website.com/04/%postname%/
320 // 1-> example-post-title
321 $permalink_data = get_sample_permalink($id);
322 $permalink_base = $permalink_data[0];
323 if ($post_type == 'post') {
324 $permalink_base = trailingslashit(str_replace('%postname%', '', $permalink_base));
325 } else {
326 $permalink_base = trailingslashit(str_replace('%pagename%', '', $permalink_base));
327 }
328
329 $slug = $permalink_data[1];
330
331 $permalink = [
332 'base' => $permalink_base,
333 'slug' => $slug,
334 ];
335
336 return $permalink;
337 }
338
339 /* WP uses $default when get_option() is empty, but it also saves empty fields
340 ** as empty strings, meaning the return value can be "" instead of the default. This is
341 ** a defensive function that guarantees we get the proper default when the setting is empty. */
342 public function get_option($name, $default)
343 {
344 $option = get_option($name, $default);
345
346 return $option === '' ? $default : $option;
347 }
348
349 public function templates()
350 {
351 return new League\Plates\Engine(dirname(__FILE__) . '/templates');
352 }
353
354 public function get_users_can_write()
355 {
356 $roles = [];
357 foreach (wp_roles()->roles as $role_name => $role_obj) {
358 if (!empty($role_obj['capabilities']['edit_posts'])) {
359 $roles[] = $role_name;
360 }
361 }
362
363 $users = get_users(['role__in' => $roles]);
364
365 return $users;
366 }
367
368 public function get_custom_types(bool $tax = false)
369 {
370 $args = [
371 'public' => true,
372 '_builtin' => false,
373 ];
374 if ($tax) {
375 return get_taxonomies($args);
376 } else {
377 return get_post_types($args);
378 }
379 }
380
381 public function filter_connect_message_on_update(
382 $message,
383 $user_first_name,
384 $product_title,
385 $user_login,
386 $site_link,
387 $freemius_link
388 ) {
389 // Add the heading HTML.
390 $plugin_name = 'Independent Analytics';
391 $title = '<h3>' . sprintf(esc_html__('We hope you love %1$s', 'iawp'), $plugin_name) . '</h3>';
392 $html = '';
393
394 // Add the introduction HTML.
395 $html .= '<p>';
396 $html .= sprintf(esc_html__('Hi, %1$s! This is an invitation to help the %2$s community. ', 'iawp'), $user_first_name, $plugin_name);
397 $html .= '<strong>';
398 $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);
399 $html .= '</strong>';
400 $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);
401 $html .= '</p>';
402
403 $html .= '<p>';
404 $html .= sprintf(esc_html__('And if you skip this, that\'s okay! %1$s will still work just fine.', 'iawp'), $plugin_name);
405 $html .= '</p>';
406
407 // Add the "Powered by" HTML.
408 $html .= '<div class="iawp-powered-by-freemius">' . esc_html__('Powered by Freemius', 'iawp') . '</div>';
409
410 return $title . $html;
411 }
412
413 public function plugin_action_links($links)
414 {
415 // Build the URL
416 $url = add_query_arg('page', 'independent-analytics', admin_url('admin.php'));
417
418 // Create the link
419 $settings_link = '<a class="calendar-link" href="' . esc_url($url) . '">' . esc_html__('Analytics Dashboard', 'iawp') . '</a>';
420
421 // Add the link to the start of the array
422 array_unshift($links, $settings_link);
423
424 return $links;
425 }
426 }
427 }
428
429 // Boot it up
430 function IAWP()
431 {
432 return Independent_Analytics::instance();
433 }
434
435 IAWP();
436