PluginProbe ʕ •ᴥ•ʔ
Post Views Counter / 1.2.13
Post Views Counter v1.2.13
1.7.13 1.7.12 1.7.11 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.2 1.3.2.1 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.7.0 1.7.1 1.7.10 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9
post-views-counter / post-views-counter.php
post-views-counter Last commit date
css 8 years ago images 8 years ago includes 8 years ago js 8 years ago languages 8 years ago index.php 8 years ago post-views-counter.php 8 years ago readme.txt 8 years ago
post-views-counter.php
517 lines
1 <?php
2 /*
3 Plugin Name: Post Views Counter
4 Description: Post Views Counter allows you to display how many times a post, page or custom post type had been viewed in a simple, fast and reliable way.
5 Version: 1.2.13
6 Author: dFactory
7 Author URI: http://www.dfactory.eu/
8 Plugin URI: http://www.dfactory.eu/plugins/post-views-counter/
9 License: MIT License
10 License URI: http://opensource.org/licenses/MIT
11 Text Domain: post-views-counter
12 Domain Path: /languages
13
14 Post Views Counter
15 Copyright (C) 2014-2018, Digital Factory - info@digitalfactory.pl
16
17 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 // exit if accessed directly
25 if ( ! defined( 'ABSPATH' ) )
26 exit;
27
28 if ( ! class_exists( 'Post_Views_Counter' ) ) :
29
30 /**
31 * Post Views Counter final class.
32 *
33 * @class Post_Views_Counter
34 * @version 1.2.13
35 */
36 final class Post_Views_Counter {
37
38 private static $instance;
39 public $options;
40 public $defaults = array(
41 'general' => array(
42 'post_types_count' => array( 'post' ),
43 'counter_mode' => 'php',
44 'post_views_column' => true,
45 'time_between_counts' => array(
46 'number' => 24,
47 'type' => 'hours'
48 ),
49 'reset_counts' => array(
50 'number' => 30,
51 'type' => 'days'
52 ),
53 'flush_interval' => array(
54 'number' => 0,
55 'type' => 'minutes'
56 ),
57 'exclude' => array(
58 'groups' => array(),
59 'roles' => array()
60 ),
61 'exclude_ips' => array(),
62 'strict_counts' => false,
63 'restrict_edit_views' => false,
64 'deactivation_delete' => false,
65 'cron_run' => true,
66 'cron_update' => true
67 ),
68 'display' => array(
69 'label' => 'Post Views:',
70 'post_types_display' => array( 'post' ),
71 'page_types_display' => array( 'singular' ),
72 'restrict_display' => array(
73 'groups' => array(),
74 'roles' => array()
75 ),
76 'position' => 'after',
77 'display_style' => array(
78 'icon' => true,
79 'text' => true
80 ),
81 'link_to_post' => true,
82 'icon_class' => 'dashicons-chart-bar'
83 ),
84 'version' => '1.2.13'
85 );
86
87 /**
88 * Disable object clone.
89 */
90 private function __clone() {
91
92 }
93
94 /**
95 * Disable unserializing of the class.
96 */
97 private function __wakeup() {
98
99 }
100
101 /**
102 * Main plugin instance,
103 * Insures that only one instance of the plugin exists in memory at one time.
104 *
105 * @return object
106 */
107 public static function instance() {
108 if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Post_Views_Counter ) ) {
109
110 self::$instance = new Post_Views_Counter;
111 self::$instance->define_constants();
112
113 // minimal setup for Fast AJAX
114 if ( defined( 'SHORTINIT' ) && SHORTINIT ) {
115 include_once( POST_VIEWS_COUNTER_PATH . 'includes/counter.php' );
116 include_once( POST_VIEWS_COUNTER_PATH . 'includes/crawler-detect.php' );
117
118 self::$instance->counter = new Post_Views_Counter_Counter();
119 self::$instance->crawler_detect = new Post_Views_Counter_Crawler_Detect();
120 // regular setup
121 } else {
122 add_action( 'plugins_loaded', array( self::$instance, 'load_textdomain' ) );
123
124 self::$instance->includes();
125
126 self::$instance->update = new Post_Views_Counter_Update();
127 self::$instance->settings = new Post_Views_Counter_Settings();
128 self::$instance->query = new Post_Views_Counter_Query();
129 self::$instance->cron = new Post_Views_Counter_Cron();
130 self::$instance->counter = new Post_Views_Counter_Counter();
131 self::$instance->columns = new Post_Views_Counter_Columns();
132 self::$instance->crawler_detect = new Post_Views_Counter_Crawler_Detect();
133 self::$instance->frontend = new Post_Views_Counter_Frontend();
134 self::$instance->dashboard = new Post_Views_Counter_Dashboard();
135 self::$instance->widgets = new Post_Views_Counter_Widgets();
136 }
137 }
138 return self::$instance;
139 }
140
141 /**
142 * Setup plugin constants.
143 *
144 * @return void
145 */
146 private function define_constants() {
147 // fix plugin_basename empty $wp_plugin_paths var
148 if ( ! ( defined( 'SHORTINIT' ) && SHORTINIT ) ) {
149 define( 'POST_VIEWS_COUNTER_URL', plugins_url( '', __FILE__ ) );
150 define( 'POST_VIEWS_COUNTER_REL_PATH', dirname( plugin_basename( __FILE__ ) ) . '/' );
151 }
152
153 define( 'POST_VIEWS_COUNTER_PATH', plugin_dir_path( __FILE__ ) );
154 }
155
156 /**
157 * Include required files.
158 *
159 * @return void
160 */
161 private function includes() {
162 include_once( POST_VIEWS_COUNTER_PATH . 'includes/update.php' );
163 include_once( POST_VIEWS_COUNTER_PATH . 'includes/settings.php' );
164 include_once( POST_VIEWS_COUNTER_PATH . 'includes/columns.php' );
165 include_once( POST_VIEWS_COUNTER_PATH . 'includes/query.php' );
166 include_once( POST_VIEWS_COUNTER_PATH . 'includes/cron.php' );
167 include_once( POST_VIEWS_COUNTER_PATH . 'includes/counter.php' );
168 include_once( POST_VIEWS_COUNTER_PATH . 'includes/crawler-detect.php' );
169 include_once( POST_VIEWS_COUNTER_PATH . 'includes/frontend.php' );
170 include_once( POST_VIEWS_COUNTER_PATH . 'includes/dashboard.php' );
171 include_once( POST_VIEWS_COUNTER_PATH . 'includes/widgets.php' );
172 }
173
174 /**
175 * Class constructor.
176 *
177 * @return void
178 */
179 public function __construct() {
180 if ( defined( 'SHORTINIT' ) && SHORTINIT ) {
181 $this->options = array(
182 'general' => array_merge( $this->defaults['general'], get_option( 'post_views_counter_settings_general', $this->defaults['general'] ) ),
183 'display' => array_merge( $this->defaults['display'], get_option( 'post_views_counter_settings_display', $this->defaults['display'] ) )
184 );
185 } else {
186 register_activation_hook( __FILE__, array( $this, 'multisite_activation' ) );
187 register_deactivation_hook( __FILE__, array( $this, 'multisite_deactivation' ) );
188
189 // settings
190 $this->options = array(
191 'general' => array_merge( $this->defaults['general'], get_option( 'post_views_counter_settings_general', $this->defaults['general'] ) ),
192 'display' => array_merge( $this->defaults['display'], get_option( 'post_views_counter_settings_display', $this->defaults['display'] ) )
193 );
194
195 // actions
196 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
197 add_action( 'wp_loaded', array( $this, 'load_pluggable_functions' ), 10 );
198
199 // filters
200 add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 2 );
201 add_filter( 'plugin_action_links', array( $this, 'plugin_action_links' ), 10, 2 );
202 }
203 }
204
205 /**
206 * Multisite activation.
207 *
208 * @global object $wpdb
209 * @param bool $networkwide
210 */
211 public function multisite_activation( $networkwide ) {
212 if ( is_multisite() && $networkwide ) {
213 global $wpdb;
214
215 $activated_blogs = array();
216 $current_blog_id = $wpdb->blogid;
217 $blogs_ids = $wpdb->get_col( $wpdb->prepare( 'SELECT blog_id FROM ' . $wpdb->blogs, '' ) );
218
219 foreach ( $blogs_ids as $blog_id ) {
220 switch_to_blog( $blog_id );
221 $this->activate_single();
222 $activated_blogs[] = (int) $blog_id;
223 }
224
225 switch_to_blog( $current_blog_id );
226 update_site_option( 'post_views_counter_activated_blogs', $activated_blogs, array() );
227 } else
228 $this->activate_single();
229 }
230
231 /**
232 * Single site activation.
233 *
234 * @global array $wp_roles
235 */
236 public function activate_single() {
237 global $wpdb, $charset_collate;
238
239 // required for dbdelta
240 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
241
242 // create post views table
243 dbDelta( '
244 CREATE TABLE IF NOT EXISTS ' . $wpdb->prefix . 'post_views (
245 id bigint unsigned NOT NULL,
246 type tinyint(1) unsigned NOT NULL,
247 period varchar(8) NOT NULL,
248 count bigint unsigned NOT NULL,
249 PRIMARY KEY (type, period, id),
250 UNIQUE INDEX id_type_period_count (id, type, period, count) USING BTREE,
251 INDEX type_period_count (type, period, count) USING BTREE
252 ) ' . $charset_collate . ';'
253 );
254
255 // add default options
256 add_option( 'post_views_counter_settings_general', $this->defaults['general'], '', 'no' );
257 add_option( 'post_views_counter_settings_display', $this->defaults['display'], '', 'no' );
258 add_option( 'post_views_counter_version', $this->defaults['version'], '', 'no' );
259
260 // schedule cache flush
261 $this->schedule_cache_flush();
262 }
263
264 /**
265 * Multisite deactivation.
266 *
267 * @global array $wpdb
268 * @param bool $networkwide
269 */
270 public function multisite_deactivation( $networkwide ) {
271 if ( is_multisite() && $networkwide ) {
272 global $wpdb;
273
274 $current_blog_id = $wpdb->blogid;
275 $blogs_ids = $wpdb->get_col( $wpdb->prepare( 'SELECT blog_id FROM ' . $wpdb->blogs, '' ) );
276
277 if ( ! ($activated_blogs = get_site_option( 'post_views_counter_activated_blogs', false, false )) )
278 $activated_blogs = array();
279
280 foreach ( $blogs_ids as $blog_id ) {
281 switch_to_blog( $blog_id );
282 $this->deactivate_single( true );
283
284 if ( in_array( (int) $blog_id, $activated_blogs, true ) )
285 unset( $activated_blogs[array_search( $blog_id, $activated_blogs )] );
286 }
287
288 switch_to_blog( $current_blog_id );
289 update_site_option( 'post_views_counter_activated_blogs', $activated_blogs );
290 } else
291 $this->deactivate_single();
292 }
293
294 /**
295 * Single site deactivation.
296 *
297 * @global array $wp_roles
298 * @param bool $multi
299 */
300 public function deactivate_single( $multi = false ) {
301 if ( $multi ) {
302 $options = get_option( 'post_views_counter_settings_general' );
303 $check = $options['deactivation_delete'];
304 } else
305 $check = $this->options['general']['deactivation_delete'];
306
307 // delete default options
308 if ( $check ) {
309 delete_option( 'post_views_counter_settings_general' );
310 delete_option( 'post_views_counter_settings_display' );
311
312 global $wpdb;
313
314 // delete table from database
315 $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'post_views' );
316 }
317
318 // remove schedule
319 wp_clear_scheduled_hook( 'pvc_reset_counts' );
320 remove_action( 'pvc_reset_counts', array( Post_Views_Counter()->cron, 'reset_counts' ) );
321
322 $this->remove_cache_flush();
323 }
324
325 /**
326 * Schedule cache flushing if it's not already scheduled.
327 *
328 * @param bool $forced
329 */
330 public function schedule_cache_flush( $forced = true ) {
331 if ( $forced || ! wp_next_scheduled( 'pvc_flush_cached_counts' ) ) {
332 wp_schedule_event( time(), 'post_views_counter_flush_interval', 'pvc_flush_cached_counts' );
333 }
334 }
335
336 /**
337 * Remove scheduled cache flush and the corresponding action.
338 */
339 public function remove_cache_flush() {
340 wp_clear_scheduled_hook( 'pvc_flush_cached_counts' );
341 remove_action( 'pvc_flush_cached_counts', array( Post_Views_Counter()->cron, 'flush_cached_counts' ) );
342 }
343
344 /**
345 * Load text domain.
346 */
347 public function load_textdomain() {
348 load_plugin_textdomain( 'post-views-counter', false, POST_VIEWS_COUNTER_REL_PATH . 'languages/' );
349 }
350
351 /**
352 * Load pluggable template functions.
353 */
354 public function load_pluggable_functions() {
355 include_once( POST_VIEWS_COUNTER_PATH . 'includes/functions.php' );
356 }
357
358 /**
359 * Enqueue admin scripts and styles.
360 *
361 * @global string $post_type
362 * @param string $page
363 */
364 public function admin_enqueue_scripts( $page ) {
365 wp_register_style(
366 'pvc-admin', POST_VIEWS_COUNTER_URL . '/css/admin.css'
367 );
368
369 wp_register_script(
370 'pvc-admin-settings', POST_VIEWS_COUNTER_URL . '/js/admin-settings.js', array( 'jquery' ), $this->defaults['version']
371 );
372
373 wp_register_script(
374 'pvc-admin-post', POST_VIEWS_COUNTER_URL . '/js/admin-post.js', array( 'jquery' ), $this->defaults['version']
375 );
376
377 wp_register_script(
378 'pvc-admin-quick-edit', POST_VIEWS_COUNTER_URL . '/js/admin-quick-edit.js', array( 'jquery', 'inline-edit-post' ), $this->defaults['version']
379 );
380
381 // load on PVC settings page
382 if ( $page === 'settings_page_post-views-counter' ) {
383
384 wp_enqueue_script( 'pvc-admin-settings' );
385
386 wp_localize_script(
387 'pvc-admin-settings', 'pvcArgsSettings', array(
388 'resetToDefaults' => __( 'Are you sure you want to reset these settings to defaults?', 'post-views-counter' ),
389 'resetViews' => __( 'Are you sure you want to delete all existing data?', 'post-views-counter' )
390 )
391 );
392
393 wp_enqueue_style( 'pvc-admin' );
394
395 // load on single post page
396 } elseif ( $page === 'post.php' || $page === 'post-new.php' ) {
397
398 $post_types = Post_Views_Counter()->options['general']['post_types_count'];
399
400 global $post_type;
401
402 if ( ! in_array( $post_type, (array) $post_types ) )
403 return;
404
405 wp_enqueue_style( 'pvc-admin' );
406 wp_enqueue_script( 'pvc-admin-post' );
407 } elseif ( $page === 'edit.php' ) {
408 $post_types = Post_Views_Counter()->options['general']['post_types_count'];
409
410 global $post_type;
411
412 if ( ! in_array( $post_type, (array) $post_types ) )
413 return;
414
415 wp_enqueue_style( 'pvc-admin' );
416
417 // woocommerce
418 if ( get_post_type() !== 'product' )
419 wp_enqueue_script( 'pvc-admin-quick-edit' );
420 }
421 }
422
423 /**
424 * Add links to plugin support forum.
425 *
426 * @param array $links
427 * @param string $file
428 * @return array
429 */
430 public function plugin_row_meta( $links, $file ) {
431
432 if ( ! current_user_can( 'install_plugins' ) )
433 return $links;
434
435 $plugin = plugin_basename( __FILE__ );
436
437 if ( $file == $plugin ) {
438 return array_merge(
439 $links, array( sprintf( '<a href="http://www.dfactory.eu/support/forum/post-views-counter/" target="_blank">%s</a>', __( 'Support', 'post-views-counter' ) ) )
440 );
441 }
442
443 return $links;
444 }
445
446 /**
447 * Add link to settings page.
448 *
449 * @staticvar string $plugin
450 * @param array $links
451 * @param string $file
452 * @return array
453 */
454 public function plugin_action_links( $links, $file ) {
455 if ( ! is_admin() || ! current_user_can( 'manage_options' ) )
456 return $links;
457
458 static $plugin;
459
460 $plugin = plugin_basename( __FILE__ );
461
462 if ( $file == $plugin ) {
463 $settings_link = sprintf( '<a href="%s">%s</a>', admin_url( 'options-general.php' ) . '?page=post-views-counter', __( 'Settings', 'post-views-counter' ) );
464
465 array_unshift( $links, $settings_link );
466 }
467
468 return $links;
469 }
470
471 /**
472 * Add admin notices.
473 */
474 public function add_notice( $html = '', $status = '', $paragraph = false ) {
475 $this->notices[] = array(
476 'html' => $html,
477 'status' => $status,
478 'paragraph' => $paragraph
479 );
480
481 add_action( 'admin_notices', array( $this, 'display_notice' ) );
482 }
483
484 /**
485 * Print admin notices.
486 */
487 public function display_notice() {
488 foreach ( $this->notices as $notice ) {
489 echo '
490 <div class="post-views-counter ' . $notice['status'] . '">
491 ' . ( $notice['paragraph'] ? '<p>' : '' ) . '
492 ' . $notice['html'] . '
493 ' . ( $notice['paragraph'] ? '</p>' : '' ) . '
494 </div>';
495 }
496 }
497 }
498
499 endif; // end if class_exists check
500
501 /**
502 * Initialise Post Views Counter.
503 *
504 * @return object
505 */
506 function Post_Views_Counter() {
507 static $instance;
508
509 // first call to instance() initializes the plugin
510 if ( $instance === null || ! ( $instance instanceof Post_Views_Counter ) )
511 $instance = Post_Views_Counter::instance();
512
513 return $instance;
514 }
515
516 Post_Views_Counter();
517