PluginProbe ʕ •ᴥ•ʔ
Post Views Counter / 1.3
Post Views Counter v1.3
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 7 years ago images 7 years ago includes 7 years ago js 7 years ago languages 7 years ago index.php 7 years ago post-views-counter.php 7 years ago readme.txt 7 years ago
post-views-counter.php
515 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.3
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-2019, 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.3
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.3'
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 include_once( POST_VIEWS_COUNTER_PATH . 'includes/functions.php' );
118
119 self::$instance->counter = new Post_Views_Counter_Counter();
120 self::$instance->crawler_detect = new Post_Views_Counter_Crawler_Detect();
121 // regular setup
122 } else {
123 add_action( 'plugins_loaded', array( self::$instance, 'load_textdomain' ) );
124
125 self::$instance->includes();
126
127 self::$instance->update = new Post_Views_Counter_Update();
128 self::$instance->settings = new Post_Views_Counter_Settings();
129 self::$instance->query = new Post_Views_Counter_Query();
130 self::$instance->cron = new Post_Views_Counter_Cron();
131 self::$instance->counter = new Post_Views_Counter_Counter();
132 self::$instance->columns = new Post_Views_Counter_Columns();
133 self::$instance->crawler_detect = new Post_Views_Counter_Crawler_Detect();
134 self::$instance->frontend = new Post_Views_Counter_Frontend();
135 self::$instance->dashboard = new Post_Views_Counter_Dashboard();
136 self::$instance->widgets = new Post_Views_Counter_Widgets();
137 }
138 }
139 return self::$instance;
140 }
141
142 /**
143 * Setup plugin constants.
144 *
145 * @return void
146 */
147 private function define_constants() {
148 // fix plugin_basename empty $wp_plugin_paths var
149 if ( ! ( defined( 'SHORTINIT' ) && SHORTINIT ) ) {
150 define( 'POST_VIEWS_COUNTER_URL', plugins_url( '', __FILE__ ) );
151 define( 'POST_VIEWS_COUNTER_REL_PATH', dirname( plugin_basename( __FILE__ ) ) . '/' );
152 }
153
154 define( 'POST_VIEWS_COUNTER_PATH', plugin_dir_path( __FILE__ ) );
155 }
156
157 /**
158 * Include required files.
159 *
160 * @return void
161 */
162 private function includes() {
163 include_once( POST_VIEWS_COUNTER_PATH . 'includes/update.php' );
164 include_once( POST_VIEWS_COUNTER_PATH . 'includes/settings.php' );
165 include_once( POST_VIEWS_COUNTER_PATH . 'includes/columns.php' );
166 include_once( POST_VIEWS_COUNTER_PATH . 'includes/query.php' );
167 include_once( POST_VIEWS_COUNTER_PATH . 'includes/cron.php' );
168 include_once( POST_VIEWS_COUNTER_PATH . 'includes/counter.php' );
169 include_once( POST_VIEWS_COUNTER_PATH . 'includes/crawler-detect.php' );
170 include_once( POST_VIEWS_COUNTER_PATH . 'includes/frontend.php' );
171 include_once( POST_VIEWS_COUNTER_PATH . 'includes/dashboard.php' );
172 include_once( POST_VIEWS_COUNTER_PATH . 'includes/widgets.php' );
173 }
174
175 /**
176 * Class constructor.
177 *
178 * @return void
179 */
180 public function __construct() {
181 if ( defined( 'SHORTINIT' ) && SHORTINIT ) {
182 $this->options = array(
183 'general' => array_merge( $this->defaults['general'], get_option( 'post_views_counter_settings_general', $this->defaults['general'] ) ),
184 'display' => array_merge( $this->defaults['display'], get_option( 'post_views_counter_settings_display', $this->defaults['display'] ) )
185 );
186 } else {
187 register_activation_hook( __FILE__, array( $this, 'multisite_activation' ) );
188 register_deactivation_hook( __FILE__, array( $this, 'multisite_deactivation' ) );
189
190 // settings
191 $this->options = array(
192 'general' => array_merge( $this->defaults['general'], get_option( 'post_views_counter_settings_general', $this->defaults['general'] ) ),
193 'display' => array_merge( $this->defaults['display'], get_option( 'post_views_counter_settings_display', $this->defaults['display'] ) )
194 );
195
196 // actions
197 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
198 add_action( 'wp_loaded', array( $this, 'load_pluggable_functions' ), 10 );
199 // add_action( 'init', array( $this, 'gutenberg_blocks' ) );
200
201 // filters
202 add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 2 );
203 add_filter( 'plugin_action_links', array( $this, 'plugin_action_links' ), 10, 2 );
204 }
205 }
206
207 /**
208 * Multisite activation.
209 *
210 * @global object $wpdb
211 * @param bool $networkwide
212 */
213 public function multisite_activation( $networkwide ) {
214 if ( is_multisite() && $networkwide ) {
215 global $wpdb;
216
217 $activated_blogs = array();
218 $current_blog_id = $wpdb->blogid;
219 $blogs_ids = $wpdb->get_col( $wpdb->prepare( 'SELECT blog_id FROM ' . $wpdb->blogs, '' ) );
220
221 foreach ( $blogs_ids as $blog_id ) {
222 switch_to_blog( $blog_id );
223 $this->activate_single();
224 $activated_blogs[] = (int) $blog_id;
225 }
226
227 switch_to_blog( $current_blog_id );
228 update_site_option( 'post_views_counter_activated_blogs', $activated_blogs, array() );
229 } else
230 $this->activate_single();
231 }
232
233 /**
234 * Single site activation.
235 *
236 * @global array $wp_roles
237 */
238 public function activate_single() {
239 global $wpdb, $charset_collate;
240
241 // required for dbdelta
242 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
243
244 // create post views table
245 dbDelta( '
246 CREATE TABLE IF NOT EXISTS ' . $wpdb->prefix . 'post_views (
247 id bigint unsigned NOT NULL,
248 type tinyint(1) unsigned NOT NULL,
249 period varchar(8) NOT NULL,
250 count bigint unsigned NOT NULL,
251 PRIMARY KEY (type, period, id),
252 UNIQUE INDEX id_type_period_count (id, type, period, count) USING BTREE,
253 INDEX type_period_count (type, period, count) USING BTREE
254 ) ' . $charset_collate . ';'
255 );
256
257 // add default options
258 add_option( 'post_views_counter_settings_general', $this->defaults['general'], '', 'no' );
259 add_option( 'post_views_counter_settings_display', $this->defaults['display'], '', 'no' );
260 add_option( 'post_views_counter_version', $this->defaults['version'], '', 'no' );
261
262 // schedule cache flush
263 $this->schedule_cache_flush();
264 }
265
266 /**
267 * Multisite deactivation.
268 *
269 * @global array $wpdb
270 * @param bool $networkwide
271 */
272 public function multisite_deactivation( $networkwide ) {
273 if ( is_multisite() && $networkwide ) {
274 global $wpdb;
275
276 $current_blog_id = $wpdb->blogid;
277 $blogs_ids = $wpdb->get_col( $wpdb->prepare( 'SELECT blog_id FROM ' . $wpdb->blogs, '' ) );
278
279 if ( ! ($activated_blogs = get_site_option( 'post_views_counter_activated_blogs', false, false )) )
280 $activated_blogs = array();
281
282 foreach ( $blogs_ids as $blog_id ) {
283 switch_to_blog( $blog_id );
284 $this->deactivate_single( true );
285
286 if ( in_array( (int) $blog_id, $activated_blogs, true ) )
287 unset( $activated_blogs[array_search( $blog_id, $activated_blogs )] );
288 }
289
290 switch_to_blog( $current_blog_id );
291 update_site_option( 'post_views_counter_activated_blogs', $activated_blogs );
292 } else
293 $this->deactivate_single();
294 }
295
296 /**
297 * Single site deactivation.
298 *
299 * @global array $wp_roles
300 * @param bool $multi
301 */
302 public function deactivate_single( $multi = false ) {
303 if ( $multi ) {
304 $options = get_option( 'post_views_counter_settings_general' );
305 $check = $options['deactivation_delete'];
306 } else
307 $check = $this->options['general']['deactivation_delete'];
308
309 // delete default options
310 if ( $check ) {
311 delete_option( 'post_views_counter_settings_general' );
312 delete_option( 'post_views_counter_settings_display' );
313
314 global $wpdb;
315
316 // delete table from database
317 $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'post_views' );
318 }
319
320 // remove schedule
321 wp_clear_scheduled_hook( 'pvc_reset_counts' );
322 remove_action( 'pvc_reset_counts', array( Post_Views_Counter()->cron, 'reset_counts' ) );
323
324 $this->remove_cache_flush();
325 }
326
327 /**
328 * Schedule cache flushing if it's not already scheduled.
329 *
330 * @param bool $forced
331 */
332 public function schedule_cache_flush( $forced = true ) {
333 if ( $forced || ! wp_next_scheduled( 'pvc_flush_cached_counts' ) )
334 wp_schedule_event( time(), 'post_views_counter_flush_interval', 'pvc_flush_cached_counts' );
335 }
336
337 /**
338 * Remove scheduled cache flush and the corresponding action.
339 */
340 public function remove_cache_flush() {
341 wp_clear_scheduled_hook( 'pvc_flush_cached_counts' );
342 remove_action( 'pvc_flush_cached_counts', array( Post_Views_Counter()->cron, 'flush_cached_counts' ) );
343 }
344
345 /**
346 * Load text domain.
347 */
348 public function load_textdomain() {
349 load_plugin_textdomain( 'post-views-counter', false, POST_VIEWS_COUNTER_REL_PATH . 'languages/' );
350 }
351
352 /**
353 * Load pluggable template functions.
354 */
355 public function load_pluggable_functions() {
356 include_once( POST_VIEWS_COUNTER_PATH . 'includes/functions.php' );
357 }
358
359 /**
360 * Add Gutenberg blocks.
361 */
362 public function gutenberg_blocks() {
363 wp_register_script( 'pvc-admin-block-views', POST_VIEWS_COUNTER_URL . '/js/admin-block.js', array( 'wp-blocks', 'wp-element', 'wp-i18n' ) );
364
365 register_block_type( 'post-views-counter/views', array( 'editor_script' => 'pvc-admin-block-views' ) );
366 }
367
368 /**
369 * Enqueue admin scripts and styles.
370 *
371 * @global string $post_type
372 * @param string $page
373 */
374 public function admin_enqueue_scripts( $page ) {
375 wp_register_style( 'pvc-admin', POST_VIEWS_COUNTER_URL . '/css/admin.css' );
376
377 wp_register_script( 'pvc-admin-settings', POST_VIEWS_COUNTER_URL . '/js/admin-settings.js', array( 'jquery' ), $this->defaults['version'] );
378 wp_register_script( 'pvc-admin-post', POST_VIEWS_COUNTER_URL . '/js/admin-post.js', array( 'jquery' ), $this->defaults['version'] );
379 wp_register_script( 'pvc-admin-quick-edit', POST_VIEWS_COUNTER_URL . '/js/admin-quick-edit.js', array( 'jquery', 'inline-edit-post' ), $this->defaults['version'] );
380
381 // load on PVC settings page
382 if ( $page === 'settings_page_post-views-counter' ) {
383 wp_enqueue_script( 'pvc-admin-settings' );
384
385 wp_localize_script(
386 'pvc-admin-settings', 'pvcArgsSettings', array(
387 'resetToDefaults' => __( 'Are you sure you want to reset these settings to defaults?', 'post-views-counter' ),
388 'resetViews' => __( 'Are you sure you want to delete all existing data?', 'post-views-counter' )
389 )
390 );
391
392 wp_enqueue_style( 'pvc-admin' );
393
394 // load on single post page
395 } elseif ( $page === 'post.php' || $page === 'post-new.php' ) {
396 $post_types = Post_Views_Counter()->options['general']['post_types_count'];
397
398 global $post_type;
399
400 if ( ! in_array( $post_type, (array) $post_types ) )
401 return;
402
403 wp_enqueue_style( 'pvc-admin' );
404 wp_enqueue_script( 'pvc-admin-post' );
405 } elseif ( $page === 'edit.php' ) {
406 $post_types = Post_Views_Counter()->options['general']['post_types_count'];
407
408 global $post_type;
409
410 if ( ! in_array( $post_type, (array) $post_types ) )
411 return;
412
413 wp_enqueue_style( 'pvc-admin' );
414
415 // woocommerce
416 if ( get_post_type() !== 'product' )
417 wp_enqueue_script( 'pvc-admin-quick-edit' );
418 } elseif ( $page === 'widgets.php' )
419 wp_enqueue_script( 'pvc-admin-widgets', POST_VIEWS_COUNTER_URL . '/js/admin-widgets.js', array( 'jquery' ), $this->defaults['version'] );
420 }
421
422 /**
423 * Add links to plugin support forum.
424 *
425 * @param array $links
426 * @param string $file
427 * @return array
428 */
429 public function plugin_row_meta( $links, $file ) {
430 if ( ! current_user_can( 'install_plugins' ) )
431 return $links;
432
433 $plugin = plugin_basename( __FILE__ );
434
435 if ( $file == $plugin ) {
436 return array_merge(
437 $links, array( sprintf( '<a href="http://www.dfactory.eu/support/forum/post-views-counter/" target="_blank">%s</a>', __( 'Support', 'post-views-counter' ) ) )
438 );
439 }
440
441 return $links;
442 }
443
444 /**
445 * Add link to settings page.
446 *
447 * @staticvar string $plugin
448 * @param array $links
449 * @param string $file
450 * @return array
451 */
452 public function plugin_action_links( $links, $file ) {
453 if ( ! is_admin() || ! current_user_can( 'manage_options' ) )
454 return $links;
455
456 static $plugin;
457
458 $plugin = plugin_basename( __FILE__ );
459
460 if ( $file == $plugin ) {
461 $settings_link = sprintf( '<a href="%s">%s</a>', admin_url( 'options-general.php' ) . '?page=post-views-counter', __( 'Settings', 'post-views-counter' ) );
462
463 array_unshift( $links, $settings_link );
464 }
465
466 return $links;
467 }
468
469 /**
470 * Add admin notices.
471 */
472 public function add_notice( $html = '', $status = '', $paragraph = false ) {
473 $this->notices[] = array(
474 'html' => $html,
475 'status' => $status,
476 'paragraph' => $paragraph
477 );
478
479 add_action( 'admin_notices', array( $this, 'display_notice' ) );
480 }
481
482 /**
483 * Print admin notices.
484 */
485 public function display_notice() {
486 foreach ( $this->notices as $notice ) {
487 echo '
488 <div class="post-views-counter ' . $notice['status'] . '">
489 ' . ( $notice['paragraph'] ? '<p>' : '' ) . '
490 ' . $notice['html'] . '
491 ' . ( $notice['paragraph'] ? '</p>' : '' ) . '
492 </div>';
493 }
494 }
495 }
496
497 endif; // end if class_exists check
498
499 /**
500 * Initialise Post Views Counter.
501 *
502 * @return object
503 */
504 function Post_Views_Counter() {
505 static $instance;
506
507 // first call to instance() initializes the plugin
508 if ( $instance === null || ! ( $instance instanceof Post_Views_Counter ) )
509 $instance = Post_Views_Counter::instance();
510
511 return $instance;
512 }
513
514 Post_Views_Counter();
515