Post Views Counter - Version 1.3

Version Description

  • New: Gutenberg compatibility
  • New: Additional options in widgets: post author and display style
  • Fix: Undefined variables when IP saving enabled
  • Fix: Check cookie not being triggered in Fast Ajax mode
  • Fix: Invalid arguments in implode function causing warning
  • Fix: Thumbnail size option did not show up after thumbnail checkbox was checked
  • Fix: Saving post (in quick edit mode too) did not update post views
Download this release

Release Info

Developer dfactory
Plugin Icon 128x128 Post Views Counter
Version 1.3
Comparing to
See all releases

Code changes from version 1.2.14 to 1.3

includes/columns.php CHANGED
@@ -18,6 +18,133 @@ class Post_Views_Counter_Columns {
18
  add_action( 'bulk_edit_custom_box', array( $this, 'quick_edit_custom_box' ), 10, 2 );
19
  add_action( 'quick_edit_custom_box', array( $this, 'quick_edit_custom_box' ), 10, 2 );
20
  add_action( 'wp_ajax_save_bulk_post_views', array( $this, 'save_bulk_post_views' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  }
22
 
23
  /**
@@ -39,15 +166,14 @@ class Post_Views_Counter_Columns {
39
  return;
40
 
41
  // get total post views
42
- $count = pvc_get_post_views( $post->ID );
43
- ?>
44
 
45
  <div class="misc-pub-section" id="post-views">
46
 
47
  <?php wp_nonce_field( 'post_views_count', 'pvc_nonce' ); ?>
48
 
49
  <span id="post-views-display">
50
- <?php echo __( 'Post Views', 'post-views-counter' ) . ': <b>' . number_format_i18n( (int) $count ) . '</b>'; ?>
51
  </span>
52
 
53
  <?php
@@ -61,8 +187,8 @@ class Post_Views_Counter_Columns {
61
  <div id="post-views-input-container" class="hide-if-js">
62
 
63
  <p><?php _e( 'Adjust the views count for this post.', 'post-views-counter' ); ?></p>
64
- <input type="hidden" name="current_post_views" id="post-views-current" value="<?php echo (int) $count; ?>" />
65
- <input type="text" name="post_views" id="post-views-input" value="<?php echo (int) $count; ?>"/><br />
66
  <p>
67
  <a href="#post-views" class="save-post-views hide-if-no-js button"><?php _e( 'OK', 'post-views-counter' ); ?></a>
68
  <a href="#post-views" class="cancel-post-views hide-if-no-js"><?php _e( 'Cancel', 'post-views-counter' ); ?></a>
@@ -96,6 +222,13 @@ class Post_Views_Counter_Columns {
96
  if ( ! isset( $_POST['post_views'] ) )
97
  return $post_id;
98
 
 
 
 
 
 
 
 
99
  // break if post views in not one of the selected
100
  $post_types = Post_Views_Counter()->options['general']['post_types_count'];
101
 
@@ -114,7 +247,7 @@ class Post_Views_Counter_Columns {
114
 
115
  global $wpdb;
116
 
117
- $count = apply_filters( 'pvc_update_post_views_count', absint( $_POST['post_views'] ), $post_id );
118
 
119
  // insert or update db post views count
120
  $wpdb->query( $wpdb->prepare( "INSERT INTO " . $wpdb->prefix . "post_views (id, type, period, count) VALUES (%d, %d, %s, %d) ON DUPLICATE KEY UPDATE count = %d", $post_id, 4, 'total', $count, $count ) );
@@ -215,7 +348,7 @@ class Post_Views_Counter_Columns {
215
  if ( $pagenow !== 'edit.php' )
216
  return;
217
 
218
- if ( $column_name != 'post_views' )
219
  return;
220
 
221
  if ( ! Post_Views_Counter()->options['general']['post_views_column'] || ! in_array( $post_type, Post_Views_Counter()->options['general']['post_types_count'] ) )
@@ -233,7 +366,8 @@ class Post_Views_Counter_Columns {
233
  <label class="inline-edit-group">
234
  <span class="title"><?php _e( 'Post Views', 'post-views-counter' ); ?></span>
235
  <span class="input-text-wrap"><input type="text" name="post_views" class="title text" value=""></span>
236
- <?php wp_nonce_field( 'post_views_count', 'pvc_nonce' ); ?>
 
237
  </label>
238
  </div>
239
  </fieldset>
@@ -247,9 +381,9 @@ class Post_Views_Counter_Columns {
247
  * @return type
248
  */
249
  function save_bulk_post_views() {
250
- if ( ! isset( $_POST['post_views'] ) ) {
251
  $count = null;
252
- } else {
253
  $count = trim( $_POST['post_views'] );
254
 
255
  if ( is_numeric( $_POST['post_views'] ) ) {
@@ -257,9 +391,8 @@ class Post_Views_Counter_Columns {
257
 
258
  if ( $count < 0 )
259
  $count = 0;
260
- } else {
261
  $count = null;
262
- }
263
  }
264
 
265
  $post_ids = ( ! empty( $_POST['post_ids'] ) && is_array( $_POST['post_ids'] ) ) ? array_map( 'absint', $_POST['post_ids'] ) : array();
18
  add_action( 'bulk_edit_custom_box', array( $this, 'quick_edit_custom_box' ), 10, 2 );
19
  add_action( 'quick_edit_custom_box', array( $this, 'quick_edit_custom_box' ), 10, 2 );
20
  add_action( 'wp_ajax_save_bulk_post_views', array( $this, 'save_bulk_post_views' ) );
21
+
22
+ // gutenberg
23
+ add_action( 'plugins_loaded', array( $this, 'init_gutemberg' ) );
24
+ }
25
+
26
+ /**
27
+ * Init Gutenberg
28
+ */
29
+ public function init_gutemberg() {
30
+ $block_editor = has_action( 'enqueue_block_assets' );
31
+ $gutenberg = function_exists( 'gutenberg_can_edit_post_type' );
32
+
33
+ if ( ! $block_editor && ! $gutenberg ) {
34
+ return;
35
+ }
36
+
37
+ add_action( 'add_meta_boxes', array( $this, 'gutenberg_add_meta_box' ) );
38
+ add_action( 'rest_api_init', array( $this, 'gutenberg_rest_api_init' ) );
39
+ add_action( 'enqueue_block_editor_assets', array( $this, 'gutenberg_enqueue_scripts' ) );
40
+ }
41
+
42
+ /**
43
+ * Register Gutenberg Metabox.
44
+ */
45
+ public function gutenberg_add_meta_box() {
46
+ add_meta_box( 'post_views_meta_box', __( 'Post Views', 'post-views-counter' ), '', 'post', '', '', array(
47
+ '__back_compat_meta_box' => false,
48
+ '__block_editor_compatible_meta_box' => true
49
+ ) );
50
+ }
51
+
52
+ /**
53
+ * Register REST API Gutenberg endpoints.
54
+ */
55
+ public function gutenberg_rest_api_init() {
56
+ // get views route
57
+ register_rest_route( 'post-views-counter', '/update-post-views/', array(
58
+ 'methods' => array( 'POST' ),
59
+ 'callback' => array( $this, 'gutenberg_update_callback' ),
60
+ 'args' => array(
61
+ 'id' => array(
62
+ 'sanitize_callback' => 'absint',
63
+ )
64
+ )
65
+ ) );
66
+ }
67
+
68
+ /**
69
+ * REST API Callback for Gutenberg endpoint.
70
+ *
71
+ * @param array $data
72
+ * @return array|int
73
+ */
74
+ public function gutenberg_update_callback( $data ) {
75
+ $post_id = ! empty( $data['id'] ) ? (int) $data['id'] : 0;
76
+ $post_views = ! empty( $data['post_views'] ) ? (int) $data['post_views'] : 0;
77
+
78
+ // get countable post types
79
+ $post_types = Post_Views_Counter()->options['general']['post_types_count'];
80
+
81
+ // check if post exists
82
+ $post = get_post( $post_id );
83
+
84
+ // whether to count this post type or not
85
+ if ( empty( $post_types ) || empty( $post ) || ! in_array( $post->post_type, $post_types, true ) )
86
+ return wp_send_json_error( __( 'Invalid post ID.', 'post-views-counter' ) );
87
+
88
+ // break if current user can't edit this post
89
+ if ( ! current_user_can( 'edit_post', $post_id ) )
90
+ return wp_send_json_error( __( 'You are not allowed to edit this item.', 'post-views-counter' ) );
91
+
92
+ // break if views editing is restricted
93
+ $restrict = (bool) Post_Views_Counter()->options['general']['restrict_edit_views'];
94
+
95
+ if ( $restrict === true && ! current_user_can( apply_filters( 'pvc_restrict_edit_capability', 'manage_options' ) ) )
96
+ return wp_send_json_error( __( 'You are not allowed to edit this item.', 'post-views-counter' ) );
97
+
98
+ global $wpdb;
99
+
100
+ $count = apply_filters( 'pvc_update_post_views_count', $post_views, $post_id );
101
+
102
+ // insert or update db post views count
103
+ $wpdb->query( $wpdb->prepare( "INSERT INTO " . $wpdb->prefix . "post_views (id, type, period, count) VALUES (%d, %d, %s, %d) ON DUPLICATE KEY UPDATE count = %d", $post_id, 4, 'total', $count, $count ) );
104
+
105
+ do_action( 'pvc_after_update_post_views_count', $post_id );
106
+
107
+ return $post_id;
108
+ }
109
+
110
+ /**
111
+ * Enqueue front end and editor JavaScript and CSS
112
+ */
113
+ public function gutenberg_enqueue_scripts() {
114
+ // enqueue the bundled block JS file
115
+ wp_enqueue_script(
116
+ 'pvc-gutenberg',
117
+ POST_VIEWS_COUNTER_URL . '/js/gutenberg.min.js',
118
+ array( 'wp-i18n', 'wp-edit-post', 'wp-element', 'wp-editor', 'wp-components', 'wp-data', 'wp-plugins', 'wp-api' ),
119
+ Post_Views_Counter()->defaults['version']
120
+ );
121
+
122
+ // restrict editing
123
+ $restrict = (bool) Post_Views_Counter()->options['general']['restrict_edit_views'];
124
+ $can_edit = $restrict === false || ( $restrict === true && current_user_can( apply_filters( 'pvc_restrict_edit_capability', 'manage_options' ) ) );
125
+
126
+ $js_args = array(
127
+ 'postID' => get_the_ID(),
128
+ 'postViews' => pvc_get_post_views( get_the_ID() ),
129
+ 'canEdit' => $can_edit,
130
+ 'nonce' => wp_create_nonce( 'wp_rest' ),
131
+ 'textPostViews' => __( 'Post Views', 'post-views-counter' ),
132
+ 'textHelp' => __( 'Adjust the views count for this post.', 'post-views-counter' ),
133
+ 'textCancel' => __( 'Cancel', 'post-views-counter' )
134
+ );
135
+
136
+ wp_localize_script(
137
+ 'pvc-gutenberg',
138
+ 'pvcEditorArgs',
139
+ $js_args
140
+ );
141
+
142
+ // enqueue frontend and editor block styles
143
+ wp_enqueue_style(
144
+ 'pvc-gutenberg',
145
+ POST_VIEWS_COUNTER_URL . '/css/gutenberg.min.css', '',
146
+ Post_Views_Counter()->defaults['version']
147
+ );
148
  }
149
 
150
  /**
166
  return;
167
 
168
  // get total post views
169
+ $count = (int) pvc_get_post_views( $post->ID ); ?>
 
170
 
171
  <div class="misc-pub-section" id="post-views">
172
 
173
  <?php wp_nonce_field( 'post_views_count', 'pvc_nonce' ); ?>
174
 
175
  <span id="post-views-display">
176
+ <?php echo __( 'Post Views', 'post-views-counter' ) . ': <b>' . number_format_i18n( $count ) . '</b>'; ?>
177
  </span>
178
 
179
  <?php
187
  <div id="post-views-input-container" class="hide-if-js">
188
 
189
  <p><?php _e( 'Adjust the views count for this post.', 'post-views-counter' ); ?></p>
190
+ <input type="hidden" name="current_post_views" id="post-views-current" value="<?php echo $count; ?>" />
191
+ <input type="text" name="post_views" id="post-views-input" value="<?php echo $count; ?>"/><br />
192
  <p>
193
  <a href="#post-views" class="save-post-views hide-if-no-js button"><?php _e( 'OK', 'post-views-counter' ); ?></a>
194
  <a href="#post-views" class="cancel-post-views hide-if-no-js"><?php _e( 'Cancel', 'post-views-counter' ); ?></a>
222
  if ( ! isset( $_POST['post_views'] ) )
223
  return $post_id;
224
 
225
+ // cast numeric post views
226
+ $post_views = (int) $_POST['post_views'];
227
+
228
+ // unchanged post views value?
229
+ if ( isset( $_POST['current_post_views'] ) && $post_views === (int) $_POST['current_post_views'] )
230
+ return $post_id;
231
+
232
  // break if post views in not one of the selected
233
  $post_types = Post_Views_Counter()->options['general']['post_types_count'];
234
 
247
 
248
  global $wpdb;
249
 
250
+ $count = apply_filters( 'pvc_update_post_views_count', $post_views, $post_id );
251
 
252
  // insert or update db post views count
253
  $wpdb->query( $wpdb->prepare( "INSERT INTO " . $wpdb->prefix . "post_views (id, type, period, count) VALUES (%d, %d, %s, %d) ON DUPLICATE KEY UPDATE count = %d", $post_id, 4, 'total', $count, $count ) );
348
  if ( $pagenow !== 'edit.php' )
349
  return;
350
 
351
+ if ( $column_name !== 'post_views' )
352
  return;
353
 
354
  if ( ! Post_Views_Counter()->options['general']['post_views_column'] || ! in_array( $post_type, Post_Views_Counter()->options['general']['post_types_count'] ) )
366
  <label class="inline-edit-group">
367
  <span class="title"><?php _e( 'Post Views', 'post-views-counter' ); ?></span>
368
  <span class="input-text-wrap"><input type="text" name="post_views" class="title text" value=""></span>
369
+ <input type="hidden" name="current_post_views" value="" />
370
+ <?php wp_nonce_field( 'post_views_count', 'pvc_nonce' ); ?>
371
  </label>
372
  </div>
373
  </fieldset>
381
  * @return type
382
  */
383
  function save_bulk_post_views() {
384
+ if ( ! isset( $_POST['post_views'] ) )
385
  $count = null;
386
+ else {
387
  $count = trim( $_POST['post_views'] );
388
 
389
  if ( is_numeric( $_POST['post_views'] ) ) {
391
 
392
  if ( $count < 0 )
393
  $count = 0;
394
+ } else
395
  $count = null;
 
396
  }
397
 
398
  $post_ids = ( ! empty( $_POST['post_ids'] ) && is_array( $_POST['post_ids'] ) ) ? array_map( 'absint', $_POST['post_ids'] ) : array();
includes/counter.php CHANGED
@@ -37,6 +37,10 @@ class Post_Views_Counter_Counter {
37
  * @param int $id
38
  */
39
  public function check_post( $id = 0 ) {
 
 
 
 
40
  // get post id
41
  $id = (int) ( empty( $id ) ? get_the_ID() : $id );
42
 
@@ -111,9 +115,8 @@ class Post_Views_Counter_Counter {
111
  // count visit
112
  if ( $count_visit ) {
113
  // strict counts?
114
- if ( Post_Views_Counter()->options['general']['strict_counts'] ) {
115
  $this->save_ip( $id );
116
- }
117
 
118
  return $this->count_visit( $id );
119
  } else
@@ -166,7 +169,7 @@ class Post_Views_Counter_Counter {
166
 
167
  exit;
168
  }
169
-
170
  /**
171
  * Check whether to count visit via Fast AJAX request.
172
  */
@@ -205,7 +208,7 @@ class Post_Views_Counter_Counter {
205
  // do we use REST API as counter?
206
  if ( Post_Views_Counter()->options['general']['counter_mode'] != 'rest_api' )
207
  return new WP_Error( 'pvc_rest_api_disabled', __( 'REST API method is disabled.', 'post-views-counter' ), array( 'status' => 404 ) );
208
-
209
  // @todo: get current user id in direct api endpoint calls
210
 
211
  // check if post exists
@@ -270,17 +273,14 @@ class Post_Views_Counter_Counter {
270
  */
271
  private function save_cookie( $id, $cookie = array(), $expired = true ) {
272
  $set_cookie = apply_filters( 'pvc_maybe_set_cookie', true );
273
-
274
  // Cookie Notice compatibility
275
- if ( function_exists( 'cn_cookies_accepted' ) ) {
276
- if ( ! cn_cookies_accepted() ) {
277
- $set_cookie = false;
278
- }
279
- }
280
-
281
- if ( $set_cookie != true )
282
  return $id;
283
-
284
  $expiration = $this->get_timestamp( Post_Views_Counter()->options['general']['time_between_counts']['type'], Post_Views_Counter()->options['general']['time_between_counts']['number'] );
285
 
286
  // assign cookie name
@@ -355,7 +355,7 @@ class Post_Views_Counter_Counter {
355
  }
356
  }
357
  }
358
-
359
  /**
360
  * Save user IP function.
361
  *
@@ -363,23 +363,26 @@ class Post_Views_Counter_Counter {
363
  */
364
  private function save_ip( $id ) {
365
  $set_cookie = apply_filters( 'pvc_maybe_set_cookie', true );
366
-
367
  // Cookie Notice compatibility
368
- if ( function_exists( 'cn_cookies_accepted' ) ) {
369
- if ( ! cn_cookies_accepted() ) {
370
- $set_cookie = false;
371
- }
372
- }
373
-
374
- if ( $set_cookie != true )
375
  return $id;
376
-
377
  // get IP cached visits
378
  $ip_cache = get_transient( 'post_views_counter_ip_cache' );
379
 
380
  if ( ! $ip_cache )
381
  $ip_cache = array();
382
 
 
 
 
 
 
 
383
  // visit exists in transient?
384
  if ( isset( $ip_cache[$id][$user_ip] ) ) {
385
  if ( $current_time > $ip_cache[$id][$user_ip] + $this->get_timestamp( Post_Views_Counter()->options['general']['time_between_counts']['type'], Post_Views_Counter()->options['general']['time_between_counts']['number'], false ) )
@@ -437,9 +440,8 @@ class Post_Views_Counter_Counter {
437
  }
438
 
439
  // update the list of cache keys to be flushed
440
- if ( $using_object_cache && ! empty( $cache_key_names ) ) {
441
  $this->update_cached_keys_list_if_needed( $cache_key_names );
442
- }
443
 
444
  do_action( 'pvc_after_count_visit', $id );
445
 
@@ -513,9 +515,8 @@ class Post_Views_Counter_Counter {
513
  */
514
  private function update_cached_keys_list_if_needed( $key_names = array() ) {
515
  $existing_list = wp_cache_get( self::NAME_ALLKEYS, self::GROUP );
516
- if ( ! $existing_list ) {
517
  $existing_list = '';
518
- }
519
 
520
  $list_modified = false;
521
 
@@ -553,9 +554,9 @@ class Post_Views_Counter_Counter {
553
 
554
  $key_names = wp_cache_get( self::NAME_ALLKEYS, self::GROUP );
555
 
556
- if ( ! $key_names ) {
557
  $key_names = array();
558
- } else {
559
  // create an array out of a string that's stored in the cache
560
  $key_names = explode( '|', $key_names );
561
  }
@@ -574,9 +575,8 @@ class Post_Views_Counter_Counter {
574
  }
575
 
576
  // delete the key holding the list itself after we've successfully flushed it
577
- if ( ! empty( $key_names ) ) {
578
  wp_cache_delete( self::NAME_ALLKEYS, self::GROUP );
579
- }
580
 
581
  return true;
582
  }
@@ -632,7 +632,7 @@ class Post_Views_Counter_Counter {
632
 
633
  return false;
634
  }
635
-
636
  /**
637
  * Check if IPv4 is in range.
638
  *
@@ -647,7 +647,7 @@ class Post_Views_Counter_Counter {
647
 
648
  return ( $ip >= (float) sprintf( "%u", ip2long( $start ) ) && $ip <= (float) sprintf( "%u", ip2long( $end ) ) );
649
  }
650
-
651
  /**
652
  * Get user real IP address.
653
  *
@@ -669,7 +669,7 @@ class Post_Views_Counter_Counter {
669
 
670
  return isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : '';
671
  }
672
-
673
  /**
674
  * Ensure an ip address is both a valid IP and does not fall within a private network range.
675
  *
@@ -677,9 +677,9 @@ class Post_Views_Counter_Counter {
677
  * @return bool
678
  */
679
  public function validate_user_ip( $ip ) {
680
- if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) === false ) {
681
  return false;
682
- }
683
  return true;
684
  }
685
 
@@ -700,6 +700,7 @@ class Post_Views_Counter_Counter {
700
  )
701
  )
702
  ) );
 
703
  // get views route
704
  register_rest_route( 'post-views-counter', '/get-post-views/', array(
705
  'methods' => array( 'GET', 'POST' ),
@@ -707,12 +708,13 @@ class Post_Views_Counter_Counter {
707
  'permission_callback' => array( $this, 'get_post_views_permissions_check' ),
708
  'args' => array(
709
  'id' => array(
710
- 'default' => 0
 
711
  )
712
  )
713
  ) );
714
  }
715
-
716
  /**
717
  * Get post views via REST API request.
718
  *
@@ -721,14 +723,10 @@ class Post_Views_Counter_Counter {
721
  */
722
  public function get_post_views_rest_api( $request ) {
723
  $post_id = is_array( $request['id'] ) ? array_map( 'absint', $request['id'] ) : absint( $request['id'] );
724
-
725
- // do we use REST API as counter?
726
- if ( Post_Views_Counter()->options['general']['counter_mode'] != 'rest_api' )
727
- return new WP_Error( 'pvc_rest_api_disabled', __( 'REST API method is disabled.', 'post-views-counter' ), array( 'status' => 404 ) );
728
-
729
  return pvc_get_post_views( $post_id );
730
  }
731
-
732
  /**
733
  * Check if a given request has access to get views
734
  *
@@ -736,7 +734,7 @@ class Post_Views_Counter_Counter {
736
  * @return WP_Error|bool
737
  */
738
  public function get_post_views_permissions_check( $request ) {
739
- return (bool) apply_filters( 'pvc_rest_api_get_post_views_check', current_user_can( 'read_posts' ), $request );
740
  }
741
 
742
  }
37
  * @param int $id
38
  */
39
  public function check_post( $id = 0 ) {
40
+ // force check post in SHORTINIT mode
41
+ if ( defined( 'SHORTINIT' ) && SHORTINIT )
42
+ $this->check_cookie();
43
+
44
  // get post id
45
  $id = (int) ( empty( $id ) ? get_the_ID() : $id );
46
 
115
  // count visit
116
  if ( $count_visit ) {
117
  // strict counts?
118
+ if ( Post_Views_Counter()->options['general']['strict_counts'] )
119
  $this->save_ip( $id );
 
120
 
121
  return $this->count_visit( $id );
122
  } else
169
 
170
  exit;
171
  }
172
+
173
  /**
174
  * Check whether to count visit via Fast AJAX request.
175
  */
208
  // do we use REST API as counter?
209
  if ( Post_Views_Counter()->options['general']['counter_mode'] != 'rest_api' )
210
  return new WP_Error( 'pvc_rest_api_disabled', __( 'REST API method is disabled.', 'post-views-counter' ), array( 'status' => 404 ) );
211
+
212
  // @todo: get current user id in direct api endpoint calls
213
 
214
  // check if post exists
273
  */
274
  private function save_cookie( $id, $cookie = array(), $expired = true ) {
275
  $set_cookie = apply_filters( 'pvc_maybe_set_cookie', true );
276
+
277
  // Cookie Notice compatibility
278
+ if ( function_exists( 'cn_cookies_accepted' ) && ! cn_cookies_accepted() )
279
+ $set_cookie = false;
280
+
281
+ if ( $set_cookie !== true )
 
 
 
282
  return $id;
283
+
284
  $expiration = $this->get_timestamp( Post_Views_Counter()->options['general']['time_between_counts']['type'], Post_Views_Counter()->options['general']['time_between_counts']['number'] );
285
 
286
  // assign cookie name
355
  }
356
  }
357
  }
358
+
359
  /**
360
  * Save user IP function.
361
  *
363
  */
364
  private function save_ip( $id ) {
365
  $set_cookie = apply_filters( 'pvc_maybe_set_cookie', true );
366
+
367
  // Cookie Notice compatibility
368
+ if ( function_exists( 'cn_cookies_accepted' ) && ! cn_cookies_accepted() )
369
+ $set_cookie = false;
370
+
371
+ if ( $set_cookie !== true )
 
 
 
372
  return $id;
373
+
374
  // get IP cached visits
375
  $ip_cache = get_transient( 'post_views_counter_ip_cache' );
376
 
377
  if ( ! $ip_cache )
378
  $ip_cache = array();
379
 
380
+ // get user IP address
381
+ $user_ip = (string) $this->get_user_ip();
382
+
383
+ // get current time
384
+ $current_time = current_time( 'timestamp', true );
385
+
386
  // visit exists in transient?
387
  if ( isset( $ip_cache[$id][$user_ip] ) ) {
388
  if ( $current_time > $ip_cache[$id][$user_ip] + $this->get_timestamp( Post_Views_Counter()->options['general']['time_between_counts']['type'], Post_Views_Counter()->options['general']['time_between_counts']['number'], false ) )
440
  }
441
 
442
  // update the list of cache keys to be flushed
443
+ if ( $using_object_cache && ! empty( $cache_key_names ) )
444
  $this->update_cached_keys_list_if_needed( $cache_key_names );
 
445
 
446
  do_action( 'pvc_after_count_visit', $id );
447
 
515
  */
516
  private function update_cached_keys_list_if_needed( $key_names = array() ) {
517
  $existing_list = wp_cache_get( self::NAME_ALLKEYS, self::GROUP );
518
+ if ( ! $existing_list )
519
  $existing_list = '';
 
520
 
521
  $list_modified = false;
522
 
554
 
555
  $key_names = wp_cache_get( self::NAME_ALLKEYS, self::GROUP );
556
 
557
+ if ( ! $key_names )
558
  $key_names = array();
559
+ else {
560
  // create an array out of a string that's stored in the cache
561
  $key_names = explode( '|', $key_names );
562
  }
575
  }
576
 
577
  // delete the key holding the list itself after we've successfully flushed it
578
+ if ( ! empty( $key_names ) )
579
  wp_cache_delete( self::NAME_ALLKEYS, self::GROUP );
 
580
 
581
  return true;
582
  }
632
 
633
  return false;
634
  }
635
+
636
  /**
637
  * Check if IPv4 is in range.
638
  *
647
 
648
  return ( $ip >= (float) sprintf( "%u", ip2long( $start ) ) && $ip <= (float) sprintf( "%u", ip2long( $end ) ) );
649
  }
650
+
651
  /**
652
  * Get user real IP address.
653
  *
669
 
670
  return isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : '';
671
  }
672
+
673
  /**
674
  * Ensure an ip address is both a valid IP and does not fall within a private network range.
675
  *
677
  * @return bool
678
  */
679
  public function validate_user_ip( $ip ) {
680
+ if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) === false )
681
  return false;
682
+
683
  return true;
684
  }
685
 
700
  )
701
  )
702
  ) );
703
+
704
  // get views route
705
  register_rest_route( 'post-views-counter', '/get-post-views/', array(
706
  'methods' => array( 'GET', 'POST' ),
708
  'permission_callback' => array( $this, 'get_post_views_permissions_check' ),
709
  'args' => array(
710
  'id' => array(
711
+ 'default' => 0,
712
+ 'user_id' => get_current_user_id()
713
  )
714
  )
715
  ) );
716
  }
717
+
718
  /**
719
  * Get post views via REST API request.
720
  *
723
  */
724
  public function get_post_views_rest_api( $request ) {
725
  $post_id = is_array( $request['id'] ) ? array_map( 'absint', $request['id'] ) : absint( $request['id'] );
726
+
 
 
 
 
727
  return pvc_get_post_views( $post_id );
728
  }
729
+
730
  /**
731
  * Check if a given request has access to get views
732
  *
734
  * @return WP_Error|bool
735
  */
736
  public function get_post_views_permissions_check( $request ) {
737
+ return (bool) apply_filters( 'pvc_rest_api_get_post_views_check', true, $request );
738
  }
739
 
740
  }
includes/crawler-detect.php CHANGED
@@ -40,14 +40,14 @@ class Post_Views_Counter_Crawler_Detect {
40
  *
41
  * @var object
42
  */
43
- protected $crawlers;
44
 
45
  /**
46
  * Exclusions object.
47
  *
48
  * @var object
49
  */
50
- protected $exclusions;
51
 
52
  /**
53
  * Headers object.
@@ -60,6 +60,9 @@ class Post_Views_Counter_Crawler_Detect {
60
  * Class constructor.
61
  */
62
  public function __construct() {
 
 
 
63
  add_action( 'after_setup_theme', array( $this, 'init' ) );
64
  }
65
 
@@ -71,8 +74,6 @@ class Post_Views_Counter_Crawler_Detect {
71
  if ( is_admin() && ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) )
72
  return;
73
 
74
- $this->crawlers = $this->get_crawlers_list();
75
- $this->exclusions = $this->get_exclusions_list();
76
  $this->ua_http_headers = $this->get_headers_list();
77
  $this->set_http_headers();
78
  $this->set_user_agent();
40
  *
41
  * @var object
42
  */
43
+ protected $crawlers = array();
44
 
45
  /**
46
  * Exclusions object.
47
  *
48
  * @var object
49
  */
50
+ protected $exclusions = array();
51
 
52
  /**
53
  * Headers object.
60
  * Class constructor.
61
  */
62
  public function __construct() {
63
+ $this->crawlers = $this->get_crawlers_list();
64
+ $this->exclusions = $this->get_exclusions_list();
65
+
66
  add_action( 'after_setup_theme', array( $this, 'init' ) );
67
  }
68
 
74
  if ( is_admin() && ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) )
75
  return;
76
 
 
 
77
  $this->ua_http_headers = $this->get_headers_list();
78
  $this->set_http_headers();
79
  $this->set_user_agent();
includes/functions.php CHANGED
@@ -33,8 +33,8 @@ if ( ! function_exists( 'pvc_get_post_views' ) ) {
33
  global $wpdb;
34
 
35
  $query = "SELECT SUM(count) AS views
36
- FROM " . $wpdb->prefix . "post_views
37
- WHERE id IN (" . $post_id . ") AND type = 4";
38
 
39
  // get cached data
40
  $post_views = wp_cache_get( md5( $query ), 'pvc-get_post_views' );
@@ -336,41 +336,43 @@ if ( ! function_exists( 'pvc_most_viewed_posts' ) ) {
336
 
337
  function pvc_most_viewed_posts( $args = array(), $display = true ) {
338
  $defaults = array(
339
- 'number_of_posts' => 5,
340
- 'post_type' => array( 'post' ),
341
- 'order' => 'desc',
342
- 'thumbnail_size' => 'thumbnail',
343
- 'show_post_views' => true,
344
- 'show_post_thumbnail' => false,
345
- 'show_post_excerpt' => false,
346
- 'no_posts_message' => __( 'No Posts', 'post-views-counter' ),
347
- 'item_before' => '',
348
- 'item_after' => ''
 
 
349
  );
350
 
351
  $args = apply_filters( 'pvc_most_viewed_posts_args', wp_parse_args( $args, $defaults ) );
352
 
353
  $args['show_post_views'] = (bool) $args['show_post_views'];
354
  $args['show_post_thumbnail'] = (bool) $args['show_post_thumbnail'];
 
355
  $args['show_post_excerpt'] = (bool) $args['show_post_excerpt'];
356
 
357
  $posts = pvc_get_most_viewed_posts(
358
- array(
359
- 'posts_per_page' => (isset( $args['number_of_posts'] ) ? (int) $args['number_of_posts'] : $defaults['number_of_posts']),
360
- 'order' => (isset( $args['order'] ) ? $args['order'] : $defaults['order']),
361
- 'post_type' => (isset( $args['post_type'] ) ? $args['post_type'] : $defaults['post_type'])
362
- )
363
  );
364
 
365
  if ( ! empty( $posts ) ) {
366
- $html = '
367
- <ul>';
368
 
369
  foreach ( $posts as $post ) {
370
  setup_postdata( $post );
371
 
372
- $html .= '
373
- <li>';
374
 
375
  $html .= apply_filters( 'pvc_most_viewed_posts_item_before', $args['item_before'], $post );
376
 
@@ -382,7 +384,7 @@ if ( ! function_exists( 'pvc_most_viewed_posts' ) ) {
382
  }
383
 
384
  $html .= '
385
- <a class="post-title" href="' . get_permalink( $post->ID ) . '">' . get_the_title( $post->ID ) . '</a>' . ($args['show_post_views'] ? ' <span class="count">(' . number_format_i18n( pvc_get_post_views( $post->ID ) ) . ')</span>' : '');
386
 
387
  $excerpt = '';
388
 
@@ -404,13 +406,12 @@ if ( ! function_exists( 'pvc_most_viewed_posts' ) ) {
404
  $html .= apply_filters( 'pvc_most_viewed_posts_item_after', $args['item_after'], $post );
405
 
406
  $html .= '
407
- </li>';
408
  }
409
 
410
  wp_reset_postdata();
411
 
412
- $html .= '
413
- </ul>';
414
  } else
415
  $html = $args['no_posts_message'];
416
 
33
  global $wpdb;
34
 
35
  $query = "SELECT SUM(count) AS views
36
+ FROM " . $wpdb->prefix . "post_views
37
+ WHERE id IN (" . $post_id . ") AND type = 4";
38
 
39
  // get cached data
40
  $post_views = wp_cache_get( md5( $query ), 'pvc-get_post_views' );
336
 
337
  function pvc_most_viewed_posts( $args = array(), $display = true ) {
338
  $defaults = array(
339
+ 'number_of_posts' => 5,
340
+ 'post_type' => array( 'post' ),
341
+ 'order' => 'desc',
342
+ 'thumbnail_size' => 'thumbnail',
343
+ 'list_type' => 'unordered',
344
+ 'show_post_views' => true,
345
+ 'show_post_thumbnail' => false,
346
+ 'show_post_author' => false,
347
+ 'show_post_excerpt' => false,
348
+ 'no_posts_message' => __( 'No Posts', 'post-views-counter' ),
349
+ 'item_before' => '',
350
+ 'item_after' => ''
351
  );
352
 
353
  $args = apply_filters( 'pvc_most_viewed_posts_args', wp_parse_args( $args, $defaults ) );
354
 
355
  $args['show_post_views'] = (bool) $args['show_post_views'];
356
  $args['show_post_thumbnail'] = (bool) $args['show_post_thumbnail'];
357
+ $args['show_post_author'] = (bool) $args['show_post_author'];
358
  $args['show_post_excerpt'] = (bool) $args['show_post_excerpt'];
359
 
360
  $posts = pvc_get_most_viewed_posts(
361
+ array(
362
+ 'posts_per_page' => ( isset( $args['number_of_posts'] ) ? (int) $args['number_of_posts'] : $defaults['number_of_posts'] ),
363
+ 'order' => ( isset( $args['order'] ) ? $args['order'] : $defaults['order'] ),
364
+ 'post_type' => ( isset( $args['post_type'] ) ? $args['post_type'] : $defaults['post_type'] )
365
+ )
366
  );
367
 
368
  if ( ! empty( $posts ) ) {
369
+ $html = ( $args['list_type'] === 'unordered' ? '<ul>' : '<ol>' );
 
370
 
371
  foreach ( $posts as $post ) {
372
  setup_postdata( $post );
373
 
374
+ $html .= '
375
+ <li>';
376
 
377
  $html .= apply_filters( 'pvc_most_viewed_posts_item_before', $args['item_before'], $post );
378
 
384
  }
385
 
386
  $html .= '
387
+ <a class="post-title" href="' . get_permalink( $post->ID ) . '">' . get_the_title( $post->ID ) . '</a>' . ( $args['show_post_author'] ? ' <span class="author">(' . get_the_author_meta( 'display_name', $post->post_author ) . ')</span> ' : '' ) . ( $args['show_post_views'] ? ' <span class="count">(' . number_format_i18n( pvc_get_post_views( $post->ID ) ) . ')</span>' : '' );
388
 
389
  $excerpt = '';
390
 
406
  $html .= apply_filters( 'pvc_most_viewed_posts_item_after', $args['item_after'], $post );
407
 
408
  $html .= '
409
+ </li>';
410
  }
411
 
412
  wp_reset_postdata();
413
 
414
+ $html .= ( $args['list_type'] === 'unordered' ? '</ul>' : '</ol>' );
 
415
  } else
416
  $html = $args['no_posts_message'];
417
 
includes/widgets.php CHANGED
@@ -34,25 +34,28 @@ class Post_Views_Counter_List_Widget extends WP_Widget {
34
  private $pvc_defaults;
35
  private $pvc_post_types;
36
  private $pvc_order_types;
 
37
  private $pvc_image_sizes;
38
 
39
  public function __construct() {
40
  parent::__construct(
41
- 'Post_Views_Counter_List_Widget', __( 'Most Viewed Posts', 'post-views-counter' ), array(
42
- 'description' => __( 'Displays a list of the most viewed posts', 'post-views-counter' )
43
- )
44
  );
45
 
46
  $this->pvc_defaults = array(
47
- 'title' => __( 'Most Viewed Posts', 'post-views-counter' ),
48
- 'number_of_posts' => 5,
49
- 'thumbnail_size' => 'thumbnail',
50
- 'post_type' => array(),
51
- 'order' => 'desc',
52
- 'show_post_views' => true,
53
- 'show_post_thumbnail' => false,
54
- 'show_post_excerpt' => false,
55
- 'no_posts_message' => __( 'No Posts found', 'post-views-counter' )
 
 
56
  );
57
 
58
  $this->pvc_order_types = array(
@@ -60,6 +63,11 @@ class Post_Views_Counter_List_Widget extends WP_Widget {
60
  'desc' => __( 'Descending', 'post-views-counter' )
61
  );
62
 
 
 
 
 
 
63
  $this->pvc_image_sizes = array_merge( array( 'full' ), get_intermediate_image_sizes() );
64
 
65
  // sort image sizes by name, ascending
@@ -103,15 +111,15 @@ class Post_Views_Counter_List_Widget extends WP_Widget {
103
  public function form( $instance ) {
104
  $html = '
105
  <p>
106
- <label for="' . $this->get_field_id( 'title' ) . '">' . __( 'Title', 'post-views-counter' ) . ':</label>
107
- <input id="' . $this->get_field_id( 'title' ) . '" class="widefat" name="' . $this->get_field_name( 'title' ) . '" type="text" value="' . esc_attr( isset( $instance['title'] ) ? $instance['title'] : $this->pvc_defaults['title'] ) . '" />
108
  </p>
109
  <p>
110
- <label>' . __( 'Post Types', 'post-views-counter' ) . ':</label><br />';
111
 
112
  foreach ( $this->pvc_post_types as $post_type => $post_type_name ) {
113
  $html .= '
114
- <input id="' . $this->get_field_id( 'post_type' ) . '-' . $post_type . '" type="checkbox" name="' . $this->get_field_name( 'post_type' ) . '[]" value="' . $post_type . '" ' . checked( ( ! isset( $instance['post_type'] ) ? true : in_array( $post_type, $instance['post_type'], true ) ), true, false ) . '><label for="' . $this->get_field_id( 'post_type' ) . '-' . $post_type . '">' . esc_html( $post_type_name ) . '</label>';
115
  }
116
 
117
  $show_post_thumbnail = isset( $instance['show_post_thumbnail'] ) ? $instance['show_post_thumbnail'] : $this->pvc_defaults['show_post_thumbnail'];
@@ -119,16 +127,16 @@ class Post_Views_Counter_List_Widget extends WP_Widget {
119
  $html .= '
120
  </p>
121
  <p>
122
- <label for="' . $this->get_field_id( 'number_of_posts' ) . '">' . __( 'Number of posts to show', 'post-views-counter' ) . ':</label>
123
- <input id="' . $this->get_field_id( 'number_of_posts' ) . '" name="' . $this->get_field_name( 'number_of_posts' ) . '" type="text" size="3" value="' . esc_attr( isset( $instance['number_of_posts'] ) ? $instance['number_of_posts'] : $this->pvc_defaults['number_of_posts'] ) . '" />
124
  </p>
125
  <p>
126
- <label for="' . $this->get_field_id( 'no_posts_message' ) . '">' . __( 'No posts message', 'post-views-counter' ) . ':</label>
127
- <input id="' . $this->get_field_id( 'no_posts_message' ) . '" class="widefat" type="text" name="' . $this->get_field_name( 'no_posts_message' ) . '" value="' . esc_attr( isset( $instance['no_posts_message'] ) ? $instance['no_posts_message'] : $this->pvc_defaults['no_posts_message'] ) . '" />
128
  </p>
129
  <p>
130
- <label for="' . $this->get_field_id( 'order' ) . '">' . __( 'Order', 'post-views-counter' ) . ':</label>
131
- <select id="' . $this->get_field_id( 'order' ) . '" name="' . $this->get_field_name( 'order' ) . '">';
132
 
133
  foreach ( $this->pvc_order_types as $id => $order ) {
134
  $html .= '
@@ -136,18 +144,32 @@ class Post_Views_Counter_List_Widget extends WP_Widget {
136
  }
137
 
138
  $html .= '
139
- </select>
 
 
 
 
 
 
 
 
 
 
 
 
140
  </p>
141
  <p>
142
- <input id="' . $this->get_field_id( 'show_post_views' ) . '" type="checkbox" name="' . $this->get_field_name( 'show_post_views' ) . '" ' . checked( true, (isset( $instance['show_post_views'] ) ? $instance['show_post_views'] : $this->pvc_defaults['show_post_views'] ), false ) . ' /> <label for="' . $this->get_field_id( 'show_post_views' ) . '">' . __( 'Display post views?', 'post-views-counter' ) . '</label>
143
- <br />
144
- <input id="' . $this->get_field_id( 'show_post_excerpt' ) . '" type="checkbox" name="' . $this->get_field_name( 'show_post_excerpt' ) . '" ' . checked( true, (isset( $instance['show_post_excerpt'] ) ? $instance['show_post_excerpt'] : $this->pvc_defaults['show_post_excerpt'] ), false ) . ' /> <label for="' . $this->get_field_id( 'show_post_excerpt' ) . '">' . __( 'Display post excerpt?', 'post-views-counter' ) . '</label>
145
- <br />
146
- <input id="' . $this->get_field_id( 'show_post_thumbnail' ) . '" class="em-show-event-thumbnail" type="checkbox" name="' . $this->get_field_name( 'show_post_thumbnail' ) . '" ' . checked( true, $show_post_thumbnail, false ) . ' /> <label for="' . $this->get_field_id( 'show_post_thumbnail' ) . '">' . __( 'Display post thumbnail?', 'post-views-counter' ) . '</label>
 
 
147
  </p>
148
- <p class="em-event-thumbnail-size"' . ($show_post_thumbnail ? '' : ' style="display: none;"') . '>
149
- <label for="' . $this->get_field_id( 'thumbnail_size' ) . '">' . __( 'Thumbnail size', 'post-views-counter' ) . ':</label>
150
- <select id="' . $this->get_field_id( 'thumbnail_size' ) . '" name="' . $this->get_field_name( 'thumbnail_size' ) . '">';
151
 
152
  $size_type = isset( $instance['thumbnail_size'] ) ? $instance['thumbnail_size'] : $this->pvc_defaults['thumbnail_size'];
153
 
@@ -157,7 +179,7 @@ class Post_Views_Counter_List_Widget extends WP_Widget {
157
  }
158
 
159
  $html .= '
160
- </select>
161
  </p>';
162
 
163
  echo $html;
@@ -177,6 +199,9 @@ class Post_Views_Counter_List_Widget extends WP_Widget {
177
  // order
178
  $old_instance['order'] = isset( $new_instance['order'] ) && in_array( $new_instance['order'], array_keys( $this->pvc_order_types ), true ) ? $new_instance['order'] : $this->pvc_defaults['order'];
179
 
 
 
 
180
  // thumbnail size
181
  $old_instance['thumbnail_size'] = isset( $new_instance['thumbnail_size'] ) && in_array( $new_instance['thumbnail_size'], $this->pvc_image_sizes, true ) ? $new_instance['thumbnail_size'] : $this->pvc_defaults['thumbnail_size'];
182
 
@@ -184,6 +209,7 @@ class Post_Views_Counter_List_Widget extends WP_Widget {
184
  $old_instance['show_post_views'] = isset( $new_instance['show_post_views'] );
185
  $old_instance['show_post_thumbnail'] = isset( $new_instance['show_post_thumbnail'] );
186
  $old_instance['show_post_excerpt'] = isset( $new_instance['show_post_excerpt'] );
 
187
 
188
  // texts
189
  $old_instance['title'] = sanitize_text_field( isset( $new_instance['title'] ) ? $new_instance['title'] : $this->pvc_defaults['title'] );
34
  private $pvc_defaults;
35
  private $pvc_post_types;
36
  private $pvc_order_types;
37
+ private $pvc_list_types;
38
  private $pvc_image_sizes;
39
 
40
  public function __construct() {
41
  parent::__construct(
42
+ 'Post_Views_Counter_List_Widget', __( 'Most Viewed Posts', 'post-views-counter' ), array(
43
+ 'description' => __( 'Displays a list of the most viewed posts', 'post-views-counter' )
44
+ )
45
  );
46
 
47
  $this->pvc_defaults = array(
48
+ 'title' => __( 'Most Viewed Posts', 'post-views-counter' ),
49
+ 'number_of_posts' => 5,
50
+ 'thumbnail_size' => 'thumbnail',
51
+ 'post_type' => array(),
52
+ 'order' => 'desc',
53
+ 'list_type' => 'unordered',
54
+ 'show_post_views' => true,
55
+ 'show_post_thumbnail' => false,
56
+ 'show_post_excerpt' => false,
57
+ 'show_post_author' => false,
58
+ 'no_posts_message' => __( 'No Posts found', 'post-views-counter' )
59
  );
60
 
61
  $this->pvc_order_types = array(
63
  'desc' => __( 'Descending', 'post-views-counter' )
64
  );
65
 
66
+ $this->pvc_list_types = array(
67
+ 'unordered' => __( 'Unordered list', 'post-views-counter' ),
68
+ 'ordered' => __( 'Ordered list', 'post-views-counter' )
69
+ );
70
+
71
  $this->pvc_image_sizes = array_merge( array( 'full' ), get_intermediate_image_sizes() );
72
 
73
  // sort image sizes by name, ascending
111
  public function form( $instance ) {
112
  $html = '
113
  <p>
114
+ <label for="' . $this->get_field_id( 'title' ) . '">' . __( 'Title', 'post-views-counter' ) . ':</label>
115
+ <input id="' . $this->get_field_id( 'title' ) . '" class="widefat" name="' . $this->get_field_name( 'title' ) . '" type="text" value="' . esc_attr( isset( $instance['title'] ) ? $instance['title'] : $this->pvc_defaults['title'] ) . '" />
116
  </p>
117
  <p>
118
+ <label>' . __( 'Post Types', 'post-views-counter' ) . ':</label><br />';
119
 
120
  foreach ( $this->pvc_post_types as $post_type => $post_type_name ) {
121
  $html .= '
122
+ <input id="' . $this->get_field_id( 'post_type' ) . '-' . $post_type . '" type="checkbox" name="' . $this->get_field_name( 'post_type' ) . '[]" value="' . $post_type . '" ' . checked( ( ! isset( $instance['post_type'] ) ? true : in_array( $post_type, $instance['post_type'], true ) ), true, false ) . '><label for="' . $this->get_field_id( 'post_type' ) . '-' . $post_type . '">' . esc_html( $post_type_name ) . '</label>';
123
  }
124
 
125
  $show_post_thumbnail = isset( $instance['show_post_thumbnail'] ) ? $instance['show_post_thumbnail'] : $this->pvc_defaults['show_post_thumbnail'];
127
  $html .= '
128
  </p>
129
  <p>
130
+ <label for="' . $this->get_field_id( 'number_of_posts' ) . '">' . __( 'Number of posts to show', 'post-views-counter' ) . ':</label>
131
+ <input id="' . $this->get_field_id( 'number_of_posts' ) . '" name="' . $this->get_field_name( 'number_of_posts' ) . '" type="text" size="3" value="' . esc_attr( isset( $instance['number_of_posts'] ) ? $instance['number_of_posts'] : $this->pvc_defaults['number_of_posts'] ) . '" />
132
  </p>
133
  <p>
134
+ <label for="' . $this->get_field_id( 'no_posts_message' ) . '">' . __( 'No posts message', 'post-views-counter' ) . ':</label>
135
+ <input id="' . $this->get_field_id( 'no_posts_message' ) . '" class="widefat" type="text" name="' . $this->get_field_name( 'no_posts_message' ) . '" value="' . esc_attr( isset( $instance['no_posts_message'] ) ? $instance['no_posts_message'] : $this->pvc_defaults['no_posts_message'] ) . '" />
136
  </p>
137
  <p>
138
+ <label for="' . $this->get_field_id( 'order' ) . '">' . __( 'Order', 'post-views-counter' ) . ':</label>
139
+ <select id="' . $this->get_field_id( 'order' ) . '" name="' . $this->get_field_name( 'order' ) . '">';
140
 
141
  foreach ( $this->pvc_order_types as $id => $order ) {
142
  $html .= '
144
  }
145
 
146
  $html .= '
147
+ </select>
148
+ </p>
149
+ <p>
150
+ <label for="' . $this->get_field_id( 'list_type' ) . '">' . __( 'Display Style', 'post-views-counter' ) . ':</label>
151
+ <select id="' . $this->get_field_id( 'list_type' ) . '" name="' . $this->get_field_name( 'list_type' ) . '">';
152
+
153
+ foreach ( $this->pvc_list_types as $id => $list_type ) {
154
+ $html .= '
155
+ <option value="' . esc_attr( $id ) . '" ' . selected( $id, ( isset( $instance['list_type'] ) ? $instance['list_type'] : $this->pvc_defaults['list_type'] ), false ) . '>' . $list_type . '</option>';
156
+ }
157
+
158
+ $html .= '
159
+ </select>
160
  </p>
161
  <p>
162
+ <input id="' . $this->get_field_id( 'show_post_views' ) . '" type="checkbox" name="' . $this->get_field_name( 'show_post_views' ) . '" ' . checked( true, (isset( $instance['show_post_views'] ) ? $instance['show_post_views'] : $this->pvc_defaults['show_post_views'] ), false ) . ' /> <label for="' . $this->get_field_id( 'show_post_views' ) . '">' . __( 'Display post views?', 'post-views-counter' ) . '</label>
163
+ <br />
164
+ <input id="' . $this->get_field_id( 'show_post_excerpt' ) . '" type="checkbox" name="' . $this->get_field_name( 'show_post_excerpt' ) . '" ' . checked( true, (isset( $instance['show_post_excerpt'] ) ? $instance['show_post_excerpt'] : $this->pvc_defaults['show_post_excerpt'] ), false ) . ' /> <label for="' . $this->get_field_id( 'show_post_excerpt' ) . '">' . __( 'Display post excerpt?', 'post-views-counter' ) . '</label>
165
+ <br />
166
+ <input id="' . $this->get_field_id( 'show_post_author' ) . '" type="checkbox" name="' . $this->get_field_name( 'show_post_author' ) . '" ' . checked( true, (isset( $instance['show_post_author'] ) ? $instance['show_post_author'] : $this->pvc_defaults['show_post_author'] ), false ) . ' /> <label for="' . $this->get_field_id( 'show_post_author' ) . '">' . __( 'Display post author?', 'post-views-counter' ) . '</label>
167
+ <br />
168
+ <input id="' . $this->get_field_id( 'show_post_thumbnail' ) . '" class="pvc-show-post-thumbnail" type="checkbox" name="' . $this->get_field_name( 'show_post_thumbnail' ) . '" ' . checked( true, $show_post_thumbnail, false ) . ' /> <label for="' . $this->get_field_id( 'show_post_thumbnail' ) . '">' . __( 'Display post thumbnail?', 'post-views-counter' ) . '</label>
169
  </p>
170
+ <p class="pvc-post-thumbnail-size"' . ( $show_post_thumbnail ? '' : ' style="display: none;"' ) . '>
171
+ <label for="' . $this->get_field_id( 'thumbnail_size' ) . '">' . __( 'Thumbnail size', 'post-views-counter' ) . ':</label>
172
+ <select id="' . $this->get_field_id( 'thumbnail_size' ) . '" name="' . $this->get_field_name( 'thumbnail_size' ) . '">';
173
 
174
  $size_type = isset( $instance['thumbnail_size'] ) ? $instance['thumbnail_size'] : $this->pvc_defaults['thumbnail_size'];
175
 
179
  }
180
 
181
  $html .= '
182
+ </select>
183
  </p>';
184
 
185
  echo $html;
199
  // order
200
  $old_instance['order'] = isset( $new_instance['order'] ) && in_array( $new_instance['order'], array_keys( $this->pvc_order_types ), true ) ? $new_instance['order'] : $this->pvc_defaults['order'];
201
 
202
+ // list type
203
+ $old_instance['list_type'] = isset( $new_instance['list_type'] ) && in_array( $new_instance['list_type'], array_keys( $this->pvc_list_types ), true ) ? $new_instance['list_type'] : $this->pvc_defaults['list_type'];
204
+
205
  // thumbnail size
206
  $old_instance['thumbnail_size'] = isset( $new_instance['thumbnail_size'] ) && in_array( $new_instance['thumbnail_size'], $this->pvc_image_sizes, true ) ? $new_instance['thumbnail_size'] : $this->pvc_defaults['thumbnail_size'];
207
 
209
  $old_instance['show_post_views'] = isset( $new_instance['show_post_views'] );
210
  $old_instance['show_post_thumbnail'] = isset( $new_instance['show_post_thumbnail'] );
211
  $old_instance['show_post_excerpt'] = isset( $new_instance['show_post_excerpt'] );
212
+ $old_instance['show_post_author'] = isset( $new_instance['show_post_author'] );
213
 
214
  // texts
215
  $old_instance['title'] = sanitize_text_field( isset( $new_instance['title'] ) ? $new_instance['title'] : $this->pvc_defaults['title'] );
js/admin-post.js CHANGED
@@ -1,19 +1,18 @@
1
- ( function ( $ ) {
2
-
3
- $( document ).ready( function () {
4
 
 
5
  // post views input
6
- $( '#post-views .edit-post-views' ).click( function () {
7
  if ( $( '#post-views-input-container' ).is( ":hidden" ) ) {
8
  $( '#post-views-input-container' ).slideDown( 'fast' );
9
  $( this ).hide();
10
  }
 
11
  return false;
12
  } );
13
 
14
  // save post views
15
- $( '#post-views .save-post-views' ).click( function () {
16
-
17
  var views = $.trim( $( '#post-views-display b' ).text() );
18
 
19
  $( '#post-views-input-container' ).slideUp( 'fast' );
@@ -29,8 +28,7 @@
29
  } );
30
 
31
  // cancel post views
32
- $( '#post-views .cancel-post-views' ).click( function () {
33
-
34
  var views = $.trim( $( '#post-views-display b' ).text() );
35
 
36
  $( '#post-views-input-container' ).slideUp( 'fast' );
@@ -43,7 +41,6 @@
43
 
44
  return false;
45
  } );
46
-
47
  } );
48
 
49
  } )( jQuery );
1
+ ( function( $ ) {
 
 
2
 
3
+ $( document ).ready( function() {
4
  // post views input
5
+ $( '#post-views .edit-post-views' ).click( function() {
6
  if ( $( '#post-views-input-container' ).is( ":hidden" ) ) {
7
  $( '#post-views-input-container' ).slideDown( 'fast' );
8
  $( this ).hide();
9
  }
10
+
11
  return false;
12
  } );
13
 
14
  // save post views
15
+ $( '#post-views .save-post-views' ).click( function() {
 
16
  var views = $.trim( $( '#post-views-display b' ).text() );
17
 
18
  $( '#post-views-input-container' ).slideUp( 'fast' );
28
  } );
29
 
30
  // cancel post views
31
+ $( '#post-views .cancel-post-views' ).click( function() {
 
32
  var views = $.trim( $( '#post-views-display b' ).text() );
33
 
34
  $( '#post-views-input-container' ).slideUp( 'fast' );
41
 
42
  return false;
43
  } );
 
44
  } );
45
 
46
  } )( jQuery );
js/admin-quick-edit.js CHANGED
@@ -1,8 +1,11 @@
1
- ( function ( $ ) {
 
2
  // we create a copy of the WP inline edit post function
3
  var $wp_inline_edit = inlineEditPost.edit;
 
4
  // and then we overwrite the function with our own code
5
- inlineEditPost.edit = function ( id ) {
 
6
  // call the original WP edit function
7
  // we don't want to leave WordPress hanging
8
  $wp_inline_edit.apply( this, arguments );
@@ -15,26 +18,29 @@
15
 
16
  if ( $post_id > 0 ) {
17
  // define the edit row
18
- var $edit_row = $( '#edit-' + $post_id );
19
- var $post_row = $( '#post-' + $post_id );
20
 
21
  // get the data
22
  var $post_views = $( '.column-post_views', $post_row ).text();
23
 
24
  // populate the data
25
  $( ':input[name="post_views"]', $edit_row ).val( $post_views );
 
26
  }
27
 
28
  return false;
29
  };
30
 
31
- $( document ).on( 'click', '#bulk_edit', function () {
 
32
  // define the bulk edit row
33
  var $bulk_row = $( '#bulk-edit' );
34
 
35
  // get the selected post ids that are being edited
36
  var $post_ids = new Array();
37
- $bulk_row.find( '#bulk-titles' ).children().each( function () {
 
38
  $post_ids.push( $( this ).attr( 'id' ).replace( /^(ttle)/i, '' ) );
39
  } );
40
 
@@ -51,7 +57,9 @@
51
  action: 'save_bulk_post_views', // this is the name of our WP AJAX function that we'll set up next
52
  post_ids: $post_ids, // and these are the 2 parameters we're passing to our function
53
  post_views: $post_views,
 
54
  }
55
  } );
56
  } );
 
57
  } )( jQuery );
1
+ ( function( $ ) {
2
+
3
  // we create a copy of the WP inline edit post function
4
  var $wp_inline_edit = inlineEditPost.edit;
5
+
6
  // and then we overwrite the function with our own code
7
+ inlineEditPost.edit = function( id ) {
8
+ console.log( 'edit' );
9
  // call the original WP edit function
10
  // we don't want to leave WordPress hanging
11
  $wp_inline_edit.apply( this, arguments );
18
 
19
  if ( $post_id > 0 ) {
20
  // define the edit row
21
+ var $edit_row = $( '#edit-' + $post_id ),
22
+ $post_row = $( '#post-' + $post_id );
23
 
24
  // get the data
25
  var $post_views = $( '.column-post_views', $post_row ).text();
26
 
27
  // populate the data
28
  $( ':input[name="post_views"]', $edit_row ).val( $post_views );
29
+ $( ':input[name="current_post_views"]', $edit_row ).val( $post_views );
30
  }
31
 
32
  return false;
33
  };
34
 
35
+ $( document ).on( 'click', '#bulk_edit', function() {
36
+ console.log( 'bulk edit' );
37
  // define the bulk edit row
38
  var $bulk_row = $( '#bulk-edit' );
39
 
40
  // get the selected post ids that are being edited
41
  var $post_ids = new Array();
42
+
43
+ $bulk_row.find( '#bulk-titles' ).children().each( function() {
44
  $post_ids.push( $( this ).attr( 'id' ).replace( /^(ttle)/i, '' ) );
45
  } );
46
 
57
  action: 'save_bulk_post_views', // this is the name of our WP AJAX function that we'll set up next
58
  post_ids: $post_ids, // and these are the 2 parameters we're passing to our function
59
  post_views: $post_views,
60
+ current_post_views: $post_views,
61
  }
62
  } );
63
  } );
64
+
65
  } )( jQuery );
js/admin-widgets.js ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ ( function ( $ ) {
2
+
3
+ $( document ).ready( function () {
4
+
5
+ $( document ).on( 'change', '.pvc-show-post-thumbnail', function () {
6
+ $( this ).closest( '.widget-content' ).find( '.pvc-post-thumbnail-size' ).fadeToggle( 300 );
7
+ } );
8
+
9
+ } );
10
+
11
+ } )( jQuery );
js/gutenberg.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(n){var i={};function o(e){if(i[e])return i[e].exports;var t=i[e]={i:e,l:!1,exports:{}};return n[e].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.m=n,o.c=i,o.d=function(e,t,n){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(t,e){if(1&e&&(t=o(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)o.d(n,i,function(e){return t[e]}.bind(null,i));return n},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="",o(o.s=0)}([function(e,t){function s(e){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function r(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function l(e){return(l=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function a(e,t){return(a=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function c(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}wp.i18n.__;var n=wp.element,i=n.Fragment,u=n.Component,o=wp.compose,p=(o.withState,o.compose,wp.data),d=p.withSelect,f=(p.withDispatch,wp.plugins.registerPlugin),w=wp.components,h=w.TextControl,v=w.Button,b=w.Popover,m=wp.editPost.PluginPostStatusInfo,g=function(e){function i(){var e,t,n;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,i),t=this,(e=!(n=l(i).apply(this,arguments))||"object"!==s(n)&&"function"!=typeof n?c(t):n).state={postViews:pvcEditorArgs.postViews,isVisible:!1},e.handleClick=e.handleClick.bind(c(c(e))),e.handleClickOutside=e.handleClickOutside.bind(c(c(e))),e.handleCancel=e.handleCancel.bind(c(c(e))),e.handleSetViews=e.handleSetViews.bind(c(c(e))),e}var t,n,o;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&a(e,t)}(i,u),t=i,o=[{key:"getDerivedStateFromProps",value:function(e,t){!e.isPublishing&&!e.isSaving||e.isAutoSaving||wp.apiRequest({path:"/post-views-counter/update-post-views/?id=".concat(e.postId),method:"POST",data:{post_views:t.postViews}}).then(function(e){return console.log(e),e},function(e){return console.log(data),e})}}],(n=[{key:"handleClick",value:function(e){e.target.classList.contains("edit-post-post-views-toggle-link")&&this.setState(function(e){return{isVisible:!e.isVisible}})}},{key:"handleClickOutside",value:function(e){e.target.classList.contains("edit-post-post-views-toggle-link")||this.setState(function(e){return{isVisible:!e.isVisible}})}},{key:"handleCancel",value:function(e){this.setState(function(e){return{postViews:pvcEditorArgs.postViews,isVisible:!e.isVisible}})}},{key:"handleSetViews",value:function(e){wp.data.dispatch("core/editor").editPost({meta:{_pvc_post_views:e}}),this.setState(function(){return{postViews:e}})}},{key:"render",value:function(){return wp.element.createElement(y,{postViews:this.state.postViews,isVisible:this.state.isVisible,handleClick:this.handleClick,handleClickOutside:this.handleClickOutside,handleCancel:this.handleCancel,handleSetViews:this.handleSetViews})}}])&&r(t.prototype,n),o&&r(t,o),i}(),y=function(e){return wp.element.createElement(i,null,wp.element.createElement(m,{className:"edit-post-post-views"},wp.element.createElement("span",null,pvcEditorArgs.textPostViews),!pvcEditorArgs.canEdit&&wp.element.createElement("span",null,e.postViews),pvcEditorArgs.canEdit&&wp.element.createElement(v,{isLink:!0,className:"edit-post-post-views-toggle-link",onClick:e.handleClick},e.postViews,e.isVisible&&wp.element.createElement(b,{position:"bottom right",className:"edit-post-post-views-popover",onClickOutside:e.handleClickOutside},wp.element.createElement("legend",null,pvcEditorArgs.textPostViews),wp.element.createElement(h,{className:"edit-post-post-views-input",type:"number",key:"post_views",value:e.postViews,onChange:e.handleSetViews}),wp.element.createElement("p",{className:"description"},pvcEditorArgs.textHelp),wp.element.createElement(v,{isLink:!0,className:"edit-post-post-views-cancel-link",onClick:e.handleCancel},pvcEditorArgs.textCancel)))))};f("post-views-counter",{icon:"",render:d(function(e,t){var n=t.forceIsSaving,i=e("core/editor"),o=i.getCurrentPostId,s=i.isSavingPost,r=i.isPublishingPost,l=i.isAutosavingPost;return{postId:o(),isSaving:n||s(),isAutoSaving:l(),isPublishing:r()}})(g)})}]);
post-views-counter.php CHANGED
@@ -2,7 +2,7 @@
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/
@@ -12,7 +12,7 @@ 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
 
@@ -31,7 +31,7 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
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
 
@@ -81,7 +81,7 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
81
  'link_to_post' => true,
82
  'icon_class' => 'dashicons-chart-bar'
83
  ),
84
- 'version' => '1.2.14'
85
  );
86
 
87
  /**
@@ -415,7 +415,8 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
415
  // woocommerce
416
  if ( get_post_type() !== 'product' )
417
  wp_enqueue_script( 'pvc-admin-quick-edit' );
418
- }
 
419
  }
420
 
421
  /**
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/
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
 
31
  * Post Views Counter final class.
32
  *
33
  * @class Post_Views_Counter
34
+ * @version 1.3
35
  */
36
  final class Post_Views_Counter {
37
 
81
  'link_to_post' => true,
82
  'icon_class' => 'dashicons-chart-bar'
83
  ),
84
+ 'version' => '1.3'
85
  );
86
 
87
  /**
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
  /**
readme.txt CHANGED
@@ -4,8 +4,8 @@ Donate link: http://www.dfactory.eu/
4
  Tags: counter, hits, posts, postviews, post views, views, count, statistics, stats, analytics, pageviews, tracking
5
  Requires at least: 4.0
6
  Requires PHP: 5.2.4
7
- Tested up to: 4.9.8
8
- Stable tag: 1.2.14
9
  License: MIT License
10
  License URI: http://opensource.org/licenses/MIT
11
 
@@ -62,6 +62,15 @@ No questions yet.
62
 
63
  == Changelog ==
64
 
 
 
 
 
 
 
 
 
 
65
  = 1.2.14 =
66
  * Fix: Bulk edit post views count reset issue
67
 
@@ -183,5 +192,5 @@ Initial release
183
 
184
  == Upgrade Notice ==
185
 
186
- = 1.2.14 =
187
- * Fix: Bulk edit post views count reset issue
4
  Tags: counter, hits, posts, postviews, post views, views, count, statistics, stats, analytics, pageviews, tracking
5
  Requires at least: 4.0
6
  Requires PHP: 5.2.4
7
+ Tested up to: 5.2.2
8
+ Stable tag: 1.3
9
  License: MIT License
10
  License URI: http://opensource.org/licenses/MIT
11
 
62
 
63
  == Changelog ==
64
 
65
+ = 1.3 =
66
+ * New: Gutenberg compatibility
67
+ * New: Additional options in widgets: post author and display style
68
+ * Fix: Undefined variables when IP saving enabled
69
+ * Fix: Check cookie not being triggered in Fast Ajax mode
70
+ * Fix: Invalid arguments in implode function causing warning
71
+ * Fix: Thumbnail size option did not show up after thumbnail checkbox was checked
72
+ * Fix: Saving post (in quick edit mode too) did not update post views
73
+
74
  = 1.2.14 =
75
  * Fix: Bulk edit post views count reset issue
76
 
192
 
193
  == Upgrade Notice ==
194
 
195
+ = 1.3.0 =
196
+ * New: Gutenberg compatibility