PluginProbe ʕ •ᴥ•ʔ
Post Views Counter / 1.2.14
Post Views Counter v1.2.14
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
514 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.14
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.14
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.14'
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 }
419 }
420
421 /**
422 * Add links to plugin support forum.
423 *
424 * @param array $links
425 * @param string $file
426 * @return array
427 */
428 public function plugin_row_meta( $links, $file ) {
429 if ( ! current_user_can( 'install_plugins' ) )
430 return $links;
431
432 $plugin = plugin_basename( __FILE__ );
433
434 if ( $file == $plugin ) {
435 return array_merge(
436 $links, array( sprintf( '<a href="http://www.dfactory.eu/support/forum/post-views-counter/" target="_blank">%s</a>', __( 'Support', 'post-views-counter' ) ) )
437 );
438 }
439
440 return $links;
441 }
442
443 /**
444 * Add link to settings page.
445 *
446 * @staticvar string $plugin
447 * @param array $links
448 * @param string $file
449 * @return array
450 */
451 public function plugin_action_links( $links, $file ) {
452 if ( ! is_admin() || ! current_user_can( 'manage_options' ) )
453 return $links;
454
455 static $plugin;
456
457 $plugin = plugin_basename( __FILE__ );
458
459 if ( $file == $plugin ) {
460 $settings_link = sprintf( '<a href="%s">%s</a>', admin_url( 'options-general.php' ) . '?page=post-views-counter', __( 'Settings', 'post-views-counter' ) );
461
462 array_unshift( $links, $settings_link );
463 }
464
465 return $links;
466 }
467
468 /**
469 * Add admin notices.
470 */
471 public function add_notice( $html = '', $status = '', $paragraph = false ) {
472 $this->notices[] = array(
473 'html' => $html,
474 'status' => $status,
475 'paragraph' => $paragraph
476 );
477
478 add_action( 'admin_notices', array( $this, 'display_notice' ) );
479 }
480
481 /**
482 * Print admin notices.
483 */
484 public function display_notice() {
485 foreach ( $this->notices as $notice ) {
486 echo '
487 <div class="post-views-counter ' . $notice['status'] . '">
488 ' . ( $notice['paragraph'] ? '<p>' : '' ) . '
489 ' . $notice['html'] . '
490 ' . ( $notice['paragraph'] ? '</p>' : '' ) . '
491 </div>';
492 }
493 }
494 }
495
496 endif; // end if class_exists check
497
498 /**
499 * Initialise Post Views Counter.
500 *
501 * @return object
502 */
503 function Post_Views_Counter() {
504 static $instance;
505
506 // first call to instance() initializes the plugin
507 if ( $instance === null || ! ( $instance instanceof Post_Views_Counter ) )
508 $instance = Post_Views_Counter::instance();
509
510 return $instance;
511 }
512
513 Post_Views_Counter();
514