Post Views Counter - Version 1.0.8

Version Description

  • New: Croation translation, thanks to Tomas Trkulja
Download this release

Release Info

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

Code changes from version 1.0.7 to 1.0.8

includes/columns.php CHANGED
@@ -1,218 +1,208 @@
1
  <?php
2
- if(!defined('ABSPATH')) exit;
 
3
 
4
  new Post_Views_Counter_Columns();
5
 
6
  class Post_Views_Counter_Columns {
7
-
8
  public function __construct() {
9
  // actions
10
- add_action('current_screen', array(&$this, 'register_new_column'));
11
- add_action('post_submitbox_misc_actions', array(&$this, 'submitbox_views'));
12
- add_action('save_post', array(&$this, 'save_post'), 10, 2);
13
  }
14
-
15
  /**
16
  * Output post views for single post.
17
  */
18
  public function submitbox_views() {
19
  global $post;
20
 
21
- $post_types = Post_Views_Counter()->get_attribute('options', 'general', 'post_types_count');
22
-
23
- if (!in_array($post->post_type, (array)$post_types))
24
  return;
25
-
26
  global $wpdb;
27
 
28
  // get total post views
29
  $views = $wpdb->get_var(
30
- $wpdb->prepare("
31
  SELECT count
32
- FROM ".$wpdb->prefix."post_views
33
- WHERE id = %d AND type = 4",
34
- absint($post->ID)
35
  )
36
  );
37
  ?>
38
 
39
  <div class="misc-pub-section" id="post-views">
40
-
41
- <?php wp_nonce_field('post_views_count', 'pvc_nonce'); ?>
42
-
43
  <span id="post-views-display">
44
-
45
- <?php echo __('Post Views', 'post-views-counter') . ': <b>' . number_format_i18n((int)$views) . '</b>'; ?>
46
 
47
  </span>
48
 
49
- <a href="#post-views" class="edit-post-views hide-if-no-js"><?php _e('Edit', 'post-views-counter'); ?></a>
50
 
51
  <div id="post-views-input-container" class="hide-if-js">
52
 
53
- <p><?php _e('Adjust the views count for this post.', 'post-views-counter'); ?></p>
54
- <input type="hidden" name="current_post_views" id="post-views-current" value="<?php echo (int)$views; ?>" />
55
- <input type="text" name="post_views" id="post-views-input" value="<?php echo (int)$views; ?>"/><br />
56
  <p>
57
- <a href="#post-views" class="save-post-views hide-if-no-js button"><?php _e('OK', 'post-views-counter'); ?></a>
58
- <a href="#post-views" class="cancel-post-views hide-if-no-js"><?php _e('Cancel', 'post-views-counter'); ?></a>
59
  </p>
60
-
61
  </div>
62
-
63
  </div>
64
  <?php
65
  }
66
 
67
  /**
68
  * Save post views data
69
- */
70
- public function save_post($post_id, $post) {
71
-
72
  // break if doing autosave
73
- if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
74
  return $post_id;
75
-
76
  // break if current user can't edit this post
77
- if(!current_user_can('edit_post', $post_id))
78
  return $post_id;
79
-
80
  // is post views set
81
- if(!isset($_POST['post_views']))
82
  return $post_id;
83
 
84
  // break if post views in not one of the selected
85
- $post_types = Post_Views_Counter()->get_attribute('options', 'general', 'post_types_count');
86
-
87
- if (!in_array($post->post_type, (array)$post_types))
88
  return $post_id;
89
-
90
  // validate data
91
- if(!isset($_POST['pvc_nonce']) || !wp_verify_nonce($_POST['pvc_nonce'], 'post_views_count'))
92
  return $post_id;
93
-
94
  global $wpdb;
95
 
96
- $count = apply_filters('pvc_update_post_views_count', absint($_POST['post_views']), $post_id);
97
-
98
  // insert or update db post views count
99
  $wpdb->query(
100
- $wpdb->prepare("
101
  INSERT INTO " . $wpdb->prefix . "post_views (id, type, period, count)
102
  VALUES (%d, %d, %s, %d)
103
- ON DUPLICATE KEY UPDATE count = %d",
104
- $post_id,
105
- 4,
106
- 'total',
107
- $count,
108
- $count
109
  )
110
  );
111
-
112
- do_action('pvc_after_update_post_views_count', $post_id);
113
  }
114
 
115
  /**
116
  * Register post views column for specific post types
117
- */
118
  public function register_new_column() {
119
  $screen = get_current_screen();
120
 
121
- if (Post_Views_Counter()->get_attribute('options', 'general', 'post_views_column') && ($screen->base == 'edit' && in_array($screen->post_type, Post_Views_Counter()->get_attribute('options', 'general', 'post_types_count')))) {
122
-
123
- foreach (Post_Views_Counter()->get_attribute('options', 'general', 'post_types_count') as $post_type) {
124
-
125
- if ($post_type === 'page' && $screen->post_type === 'page') {
126
  // actions
127
- add_action('manage_pages_custom_column', array(&$this, 'add_new_column_content'), 10, 2);
128
 
129
  // filters
130
- add_filter('manage_pages_columns', array(&$this, 'add_new_column'));
131
- add_filter('manage_edit-page_sortable_columns', array(&$this, 'register_sortable_custom_column'));
132
- }
133
- elseif ($post_type === 'post' && $screen->post_type === 'post') {
134
  // actions
135
- add_action('manage_posts_custom_column', array(&$this, 'add_new_column_content'), 10, 2);
136
 
137
  // filters
138
- add_filter('manage_posts_columns', array(&$this, 'add_new_column'));
139
- add_filter('manage_edit-post_sortable_columns', array(&$this, 'register_sortable_custom_column'));
140
- }
141
- elseif ($screen->post_type === $post_type) {
142
  // actions
143
- add_action('manage_'.$post_type.'_posts_custom_column', array(&$this, 'add_new_column_content'), 10, 2);
144
 
145
  // filters
146
- add_filter('manage_'.$post_type.'_posts_columns', array(&$this, 'add_new_column'));
147
- add_filter('manage_edit-'.$post_type.'_sortable_columns', array(&$this, 'register_sortable_custom_column'));
148
  }
149
-
150
  }
151
  }
152
  }
153
 
154
  /**
155
  * Register sortable post views column
156
- */
157
- public function register_sortable_custom_column($columns) {
158
  // add new sortable column
159
  $columns['post_views'] = 'post_views';
160
 
161
  return $columns;
162
  }
163
-
164
  /**
165
  * Add post views column
166
- */
167
- public function add_new_column($columns) {
168
  $offset = 0;
169
 
170
- if (isset($columns['date']))
171
- $offset++;
172
 
173
- if (isset($columns['comments']))
174
- $offset++;
175
 
176
- if ($offset > 0) {
177
- $date = array_slice($columns, -$offset, $offset, true);
178
 
179
- foreach ($date as $column => $name) {
180
- unset($columns[$column]);
181
  }
182
 
183
- $columns['post_views'] = __('Post Views', 'post-views-counter');
184
 
185
- foreach ($date as $column => $name) {
186
  $columns[$column] = $name;
187
  }
188
- }
189
- else
190
- $columns['post_views'] = __('Post Views', 'post-views-counter');
191
 
192
  return $columns;
193
  }
194
 
195
  /**
196
  * Add post views column content
197
- */
198
- public function add_new_column_content($column_name, $id) {
199
-
200
- if ($column_name === 'post_views') {
201
-
202
  global $wpdb;
203
 
204
  // get total post views
205
  $views = $wpdb->get_var(
206
- $wpdb->prepare("
207
  SELECT count
208
- FROM ".$wpdb->prefix."post_views
209
- WHERE id = %d AND type = 4",
210
- $id
211
  )
212
  );
213
 
214
- echo number_format_i18n((int)$views);
215
  }
216
  }
 
217
  }
218
- ?>
1
  <?php
2
+ if ( ! defined( 'ABSPATH' ) )
3
+ exit;
4
 
5
  new Post_Views_Counter_Columns();
6
 
7
  class Post_Views_Counter_Columns {
8
+
9
  public function __construct() {
10
  // actions
11
+ add_action( 'current_screen', array( &$this, 'register_new_column' ) );
12
+ add_action( 'post_submitbox_misc_actions', array( &$this, 'submitbox_views' ) );
13
+ add_action( 'save_post', array( &$this, 'save_post' ), 10, 2 );
14
  }
15
+
16
  /**
17
  * Output post views for single post.
18
  */
19
  public function submitbox_views() {
20
  global $post;
21
 
22
+ $post_types = Post_Views_Counter()->get_attribute( 'options', 'general', 'post_types_count' );
23
+
24
+ if ( ! in_array( $post->post_type, (array) $post_types ) )
25
  return;
26
+
27
  global $wpdb;
28
 
29
  // get total post views
30
  $views = $wpdb->get_var(
31
+ $wpdb->prepare( "
32
  SELECT count
33
+ FROM " . $wpdb->prefix . "post_views
34
+ WHERE id = %d AND type = 4", absint( $post->ID )
 
35
  )
36
  );
37
  ?>
38
 
39
  <div class="misc-pub-section" id="post-views">
40
+
41
+ <?php wp_nonce_field( 'post_views_count', 'pvc_nonce' ); ?>
42
+
43
  <span id="post-views-display">
44
+
45
+ <?php echo __( 'Post Views', 'post-views-counter' ) . ': <b>' . number_format_i18n( (int) $views ) . '</b>'; ?>
46
 
47
  </span>
48
 
49
+ <a href="#post-views" class="edit-post-views hide-if-no-js"><?php _e( 'Edit', 'post-views-counter' ); ?></a>
50
 
51
  <div id="post-views-input-container" class="hide-if-js">
52
 
53
+ <p><?php _e( 'Adjust the views count for this post.', 'post-views-counter' ); ?></p>
54
+ <input type="hidden" name="current_post_views" id="post-views-current" value="<?php echo (int) $views; ?>" />
55
+ <input type="text" name="post_views" id="post-views-input" value="<?php echo (int) $views; ?>"/><br />
56
  <p>
57
+ <a href="#post-views" class="save-post-views hide-if-no-js button"><?php _e( 'OK', 'post-views-counter' ); ?></a>
58
+ <a href="#post-views" class="cancel-post-views hide-if-no-js"><?php _e( 'Cancel', 'post-views-counter' ); ?></a>
59
  </p>
60
+
61
  </div>
62
+
63
  </div>
64
  <?php
65
  }
66
 
67
  /**
68
  * Save post views data
69
+ */
70
+ public function save_post( $post_id, $post ) {
71
+
72
  // break if doing autosave
73
+ if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
74
  return $post_id;
75
+
76
  // break if current user can't edit this post
77
+ if ( ! current_user_can( 'edit_post', $post_id ) )
78
  return $post_id;
79
+
80
  // is post views set
81
+ if ( ! isset( $_POST['post_views'] ) )
82
  return $post_id;
83
 
84
  // break if post views in not one of the selected
85
+ $post_types = Post_Views_Counter()->get_attribute( 'options', 'general', 'post_types_count' );
86
+
87
+ if ( ! in_array( $post->post_type, (array) $post_types ) )
88
  return $post_id;
89
+
90
  // validate data
91
+ if ( ! isset( $_POST['pvc_nonce'] ) || ! wp_verify_nonce( $_POST['pvc_nonce'], 'post_views_count' ) )
92
  return $post_id;
93
+
94
  global $wpdb;
95
 
96
+ $count = apply_filters( 'pvc_update_post_views_count', absint( $_POST['post_views'] ), $post_id );
97
+
98
  // insert or update db post views count
99
  $wpdb->query(
100
+ $wpdb->prepare( "
101
  INSERT INTO " . $wpdb->prefix . "post_views (id, type, period, count)
102
  VALUES (%d, %d, %s, %d)
103
+ ON DUPLICATE KEY UPDATE count = %d", $post_id, 4, 'total', $count, $count
 
 
 
 
 
104
  )
105
  );
106
+
107
+ do_action( 'pvc_after_update_post_views_count', $post_id );
108
  }
109
 
110
  /**
111
  * Register post views column for specific post types
112
+ */
113
  public function register_new_column() {
114
  $screen = get_current_screen();
115
 
116
+ if ( Post_Views_Counter()->get_attribute( 'options', 'general', 'post_views_column' ) && ($screen->base == 'edit' && in_array( $screen->post_type, Post_Views_Counter()->get_attribute( 'options', 'general', 'post_types_count' ) )) ) {
117
+
118
+ foreach ( Post_Views_Counter()->get_attribute( 'options', 'general', 'post_types_count' ) as $post_type ) {
119
+
120
+ if ( $post_type === 'page' && $screen->post_type === 'page' ) {
121
  // actions
122
+ add_action( 'manage_pages_custom_column', array( &$this, 'add_new_column_content' ), 10, 2 );
123
 
124
  // filters
125
+ add_filter( 'manage_pages_columns', array( &$this, 'add_new_column' ) );
126
+ add_filter( 'manage_edit-page_sortable_columns', array( &$this, 'register_sortable_custom_column' ) );
127
+ } elseif ( $post_type === 'post' && $screen->post_type === 'post' ) {
 
128
  // actions
129
+ add_action( 'manage_posts_custom_column', array( &$this, 'add_new_column_content' ), 10, 2 );
130
 
131
  // filters
132
+ add_filter( 'manage_posts_columns', array( &$this, 'add_new_column' ) );
133
+ add_filter( 'manage_edit-post_sortable_columns', array( &$this, 'register_sortable_custom_column' ) );
134
+ } elseif ( $screen->post_type === $post_type ) {
 
135
  // actions
136
+ add_action( 'manage_' . $post_type . '_posts_custom_column', array( &$this, 'add_new_column_content' ), 10, 2 );
137
 
138
  // filters
139
+ add_filter( 'manage_' . $post_type . '_posts_columns', array( &$this, 'add_new_column' ) );
140
+ add_filter( 'manage_edit-' . $post_type . '_sortable_columns', array( &$this, 'register_sortable_custom_column' ) );
141
  }
 
142
  }
143
  }
144
  }
145
 
146
  /**
147
  * Register sortable post views column
148
+ */
149
+ public function register_sortable_custom_column( $columns ) {
150
  // add new sortable column
151
  $columns['post_views'] = 'post_views';
152
 
153
  return $columns;
154
  }
155
+
156
  /**
157
  * Add post views column
158
+ */
159
+ public function add_new_column( $columns ) {
160
  $offset = 0;
161
 
162
+ if ( isset( $columns['date'] ) )
163
+ $offset ++;
164
 
165
+ if ( isset( $columns['comments'] ) )
166
+ $offset ++;
167
 
168
+ if ( $offset > 0 ) {
169
+ $date = array_slice( $columns, -$offset, $offset, true );
170
 
171
+ foreach ( $date as $column => $name ) {
172
+ unset( $columns[$column] );
173
  }
174
 
175
+ $columns['post_views'] = __( 'Post Views', 'post-views-counter' );
176
 
177
+ foreach ( $date as $column => $name ) {
178
  $columns[$column] = $name;
179
  }
180
+ } else
181
+ $columns['post_views'] = __( 'Post Views', 'post-views-counter' );
 
182
 
183
  return $columns;
184
  }
185
 
186
  /**
187
  * Add post views column content
188
+ */
189
+ public function add_new_column_content( $column_name, $id ) {
190
+
191
+ if ( $column_name === 'post_views' ) {
192
+
193
  global $wpdb;
194
 
195
  // get total post views
196
  $views = $wpdb->get_var(
197
+ $wpdb->prepare( "
198
  SELECT count
199
+ FROM " . $wpdb->prefix . "post_views
200
+ WHERE id = %d AND type = 4", $id
 
201
  )
202
  );
203
 
204
+ echo number_format_i18n( (int) $views );
205
  }
206
  }
207
+
208
  }
 
includes/counter.php CHANGED
@@ -1,55 +1,56 @@
1
  <?php
2
- if(!defined('ABSPATH')) exit;
 
3
 
4
  new Post_Views_Counter_Counter();
5
 
6
  class Post_Views_Counter_Counter {
7
-
8
- const GROUP = 'pvc';
9
- const NAME_ALLKEYS = 'cached_key_names';
10
  const CACHE_KEY_SEPARATOR = '.';
11
 
12
  private $cookie = array(
13
- 'exists' => false,
14
- 'visited_posts' => array(),
15
- 'expiration' => 0
16
  );
17
 
18
  public function __construct() {
19
  // set instance
20
- Post_Views_Counter()->add_instance('counter', $this);
21
 
22
  // actions
23
- add_action('plugins_loaded', array(&$this, 'check_cookie'), 1);
24
- add_action('wp', array(&$this, 'check_post'));
25
- add_action('deleted_post', array(&$this, 'delete_post_views'));
26
- add_action('wp_ajax_pvc-check-post', array(&$this, 'check_post_ajax'));
27
- add_action('wp_ajax_nopriv_pvc-check-post', array(&$this, 'check_post_ajax'));
28
  }
29
 
30
  /**
31
- * Remove post views from database when post is deleted
32
- */
33
- public function delete_post_views($post_id) {
34
  global $wpdb;
35
 
36
- $wpdb->delete($wpdb->prefix.'post_views', array('id' => $post_id), array('%d'));
37
  }
38
 
39
  /**
40
- * Check whether user has excluded roles
41
- */
42
- public function is_user_roles_excluded($option) {
43
  $user = wp_get_current_user();
44
 
45
- if (empty($user))
46
  return false;
47
 
48
- $roles = (array)$user->roles;
49
 
50
- if (!empty($roles)) {
51
- foreach ($roles as $role) {
52
- if (in_array($role, $option, true))
53
  return true;
54
  }
55
  }
@@ -58,201 +59,198 @@ class Post_Views_Counter_Counter {
58
  }
59
 
60
  /**
61
- * Get timestamp convertion
62
- */
63
- public function get_timestamp($type, $number, $timestamp = true) {
64
  $converter = array(
65
- 'minutes' => 60,
66
- 'hours' => 3600,
67
- 'days' => 86400,
68
- 'weeks' => 604800,
69
- 'months' => 2592000,
70
- 'years' => 946080000
71
  );
72
 
73
- return ($timestamp ? current_time('timestamp', true) : 0) + $number * $converter[$type];
74
  }
75
 
76
  /**
77
- * Check whether to count visit via AJAX request
78
- */
79
  public function check_post_ajax() {
80
- if (isset($_POST['action'], $_POST['post_id'], $_POST['pvc_nonce'], $_POST['post_type']) && $_POST['action'] === 'pvc-check-post' && ($post_id = (int)$_POST['post_id']) > 0 && wp_verify_nonce($_POST['pvc_nonce'], 'pvc-check-post') !== false && Post_Views_Counter()->get_attribute('options', 'general', 'counter_mode') === 'js') {
81
  // get countable post types
82
- $post_types = Post_Views_Counter()->get_attribute('options', 'general', 'post_types_count');
83
 
84
  // get post type
85
- $post_type = get_post_type($post_id);
86
 
87
  // whether to count this post type or not
88
- if (empty($post_types) || empty($post_type) || $post_type !== $_POST['post_type'] || !in_array($post_type, $post_types, true))
89
  exit;
90
 
91
  // get excluded ips
92
- $excluded_ips = Post_Views_Counter()->get_attribute('options', 'general', 'exclude_ips');
93
 
94
  // whether to count this ip or not
95
- if (!empty($excluded_ips) && filter_var(preg_replace('/[^0-9a-fA-F:., ]/', '', $_SERVER['REMOTE_ADDR']), FILTER_VALIDATE_IP) && in_array($_SERVER['REMOTE_ADDR'], $excluded_ips, true))
96
  exit;
97
 
98
  // get groups to check them faster
99
- $groups = Post_Views_Counter()->get_attribute('options', 'general', 'exclude', 'groups');
100
 
101
  // whether to count this user
102
- if (is_user_logged_in()) {
103
  // exclude logged in users?
104
- if (in_array('users', $groups, true))
105
  exit;
106
  // exclude specific roles?
107
- elseif (in_array('roles', $groups, true) && $this->is_user_roles_excluded(Post_Views_Counter()->get_attribute('options', 'general', 'exclude', 'roles')))
108
  exit;
109
  }
110
  // exclude guests?
111
- elseif (in_array('guests', $groups, true))
112
  exit;
113
 
114
  // whether to count robots
115
- if ($this->is_robot())
116
  exit;
117
 
118
  // cookie already existed?
119
- if ($this->cookie['exists']) {
120
  // post already viewed but not expired?
121
- if(in_array($post_id, array_keys($this->cookie['visited_posts']), true) && current_time('timestamp', true) < $this->cookie['visited_posts'][$post_id]) {
122
  // updates cookie but do not count visit
123
- $this->save_cookie($post_id, $this->cookie, false);
124
 
125
  exit;
126
- }
127
- else
128
- // updates cookie
129
- $this->save_cookie($post_id, $this->cookie);
130
  } else {
131
  // set new cookie
132
- $this->save_cookie($post_id);
133
  }
134
 
135
  // count visit
136
- $this->count_visit($post_id);
137
  }
138
 
139
  exit;
140
  }
141
 
142
  /**
143
- * Check whether to count visit
144
- */
145
  public function check_post() {
146
  // do not count admin entries
147
- if (is_admin())
148
  return;
149
 
150
  // do we use PHP as counter?
151
- if (Post_Views_Counter()->get_attribute('options', 'general', 'counter_mode') === 'php') {
152
- $post_types = Post_Views_Counter()->get_attribute('options', 'general', 'post_types_count');
153
 
154
  // whether to count this post type
155
- if (empty($post_types) || !is_singular($post_types))
156
  return;
157
 
158
- $ips = Post_Views_Counter()->get_attribute('options', 'general', 'exclude_ips');
159
 
160
  // whether to count this ip
161
- if (!empty($ips) && filter_var(preg_replace('/[^0-9a-fA-F:., ]/', '', $_SERVER['REMOTE_ADDR']), FILTER_VALIDATE_IP) && in_array($_SERVER['REMOTE_ADDR'], $ips, true))
162
  return;
163
 
164
  // get groups to check them faster
165
- $groups = Post_Views_Counter()->get_attribute('options', 'general', 'exclude', 'groups');
166
 
167
  // whether to count this user
168
- if (is_user_logged_in()) {
169
  // exclude logged in users?
170
- if (in_array('users', $groups, true))
171
  return;
172
  // exclude specific roles?
173
- elseif (in_array('roles', $groups, true) && $this->is_user_roles_excluded(Post_Views_Counter()->get_attribute('options', 'general', 'exclude', 'roles')))
174
  return;
175
  }
176
  // exclude guests?
177
- elseif (in_array('guests', $groups, true))
178
  return;
179
 
180
  // whether to count robots
181
- if ($this->is_robot())
182
  return;
183
 
184
  // get post id
185
  $id = get_the_ID();
186
 
187
  // cookie already existed?
188
- if ($this->cookie['exists']) {
189
  // post already viewed but not expired?
190
- if (in_array($id, array_keys($this->cookie['visited_posts']), true) && current_time('timestamp', true) < $this->cookie['visited_posts'][$id]) {
191
  // update cookie but do not count visit
192
- $this->save_cookie($id, $this->cookie, false);
193
 
194
  return;
195
- }
196
- else
197
- // update cookie
198
- $this->save_cookie($id, $this->cookie);
199
- }
200
- else
201
- // set new cookie
202
- $this->save_cookie($id);
203
 
204
  // count visit
205
- $this->count_visit($id);
206
  }
207
  }
208
 
209
  /**
210
- * Initialize cookie session
211
- */
212
  public function check_cookie() {
213
  // do not run in admin except for ajax requests
214
- if (is_admin() && !(defined('DOING_AJAX') && DOING_AJAX))
215
  return;
216
 
217
  // is cookie set?
218
- if (isset($_COOKIE['pvc_visits']) && !empty($_COOKIE['pvc_visits'])) {
219
  $visited_posts = $expirations = array();
220
 
221
- foreach ($_COOKIE['pvc_visits'] as $content) {
222
  // is cookie valid?
223
- if (preg_match('/^(([0-9]+b[0-9]+a?)+)$/', $content) === 1) {
224
  // get single id with expiration
225
- $expiration_ids = explode('a', $content);
226
 
227
  // check every expiration => id pair
228
- foreach ($expiration_ids as $pair) {
229
- $pair = explode('b', $pair);
230
- $expirations[] = (int)$pair[0];
231
- $visited_posts[(int)$pair[1]] = (int)$pair[0];
232
  }
233
  }
234
  }
235
 
236
  $this->cookie = array(
237
- 'exists' => true,
238
- 'visited_posts' => $visited_posts,
239
- 'expiration' => max($expirations)
240
  );
241
  }
242
  }
243
 
244
  /**
245
- * Save cookie function
246
- */
247
- private function save_cookie($id, $cookie = array(), $expired = true) {
248
- $expiration = $this->get_timestamp(Post_Views_Counter()->get_attribute('options', 'general', 'time_between_counts', 'type'), Post_Views_Counter()->get_attribute('options', 'general', 'time_between_counts', 'number'));
249
 
250
  // is this a new cookie?
251
- if (empty($cookie)) {
252
  // set cookie
253
- setcookie('pvc_visits[0]', $expiration.'b'.$id, $expiration, COOKIEPATH, COOKIE_DOMAIN, (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? true : false), true);
254
  } else {
255
- if ($expired) {
256
  // add new id or chang expiration date if id already exists
257
  $cookie['visited_posts'][$id] = $expiration;
258
  }
@@ -261,122 +259,120 @@ class Post_Views_Counter_Counter {
261
  $visited_posts_expirations = $cookie['visited_posts'];
262
 
263
  // get current gmt time
264
- $time = current_time('timestamp', true);
265
 
266
  // check whether viewed id has expired - no need to keep it in cookie (less size)
267
- foreach ($visited_posts_expirations as $post_id => $post_expiration) {
268
- if ($time > $post_expiration)
269
- unset($cookie['visited_posts'][$post_id]);
270
  }
271
 
272
  // set new last expiration date if needed
273
- $cookie['expiration'] = max($cookie['visited_posts']);
274
 
275
  $cookies = $imploded = array();
276
 
277
  // create pairs
278
- foreach ($cookie['visited_posts'] as $id => $exp) {
279
- $imploded[] = $exp.'b'.$id;
280
  }
281
 
282
  // split cookie into chunks (4000 bytes to make sure it is safe for every browser)
283
- $chunks = str_split(implode('a', $imploded), 4000);
284
 
285
  // more then one chunk?
286
- if (count($chunks) > 1) {
287
  $last_id = '';
288
 
289
- foreach ($chunks as $chunk_id => $chunk) {
290
  // new chunk
291
- $chunk_c = $last_id.$chunk;
292
 
293
  // is it full-length chunk?
294
- if (strlen($chunk) === 4000) {
295
  // get last part
296
- $last_part = strrchr($chunk_c, 'a');
297
 
298
  // get last id
299
- $last_id = substr($last_part, 1);
300
 
301
  // add new full-lenght chunk
302
- $cookies[$chunk_id] = substr($chunk_c, 0, strlen($chunk_c) - strlen($last_part));
303
  } else {
304
  // add last chunk
305
  $cookies[$chunk_id] = $chunk_c;
306
  }
307
  }
308
-
309
  } else {
310
  // only one chunk
311
  $cookies[] = $chunks[0];
312
  }
313
 
314
- foreach ($cookies as $key => $value) {
315
  // set cookie
316
- setcookie('pvc_visits['.$key.']', $value, $cookie['expiration'], COOKIEPATH, COOKIE_DOMAIN, (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? true : false), true);
317
  }
318
  }
319
  }
320
 
321
-
322
- public function using_object_cache($using = null) {
 
 
323
  $using = wp_using_ext_object_cache( $using );
324
 
325
  if ( $using ) {
326
- // Check if explicitly disabled by flush_interval setting/option <= 0
327
- $flush_interval_number = Post_Views_Counter()->get_attribute('options', 'general', 'flush_interval', 'number');
328
  $using = ( $flush_interval_number <= 0 ) ? false : true;
329
  }
330
 
331
  return $using;
332
  }
333
 
334
-
335
  /**
336
- *
337
- */
338
- private function count_visit($id) {
339
  global $wpdb;
340
 
341
- $cache_key_names = array();
342
  $using_object_cache = $this->using_object_cache();
343
 
344
- // gets day, week, month and year
345
- $date = explode('-', date('W-d-m-Y', current_time('timestamp')));
346
-
347
- foreach (array(
348
- 0 => $date[3].$date[2].$date[1], // day like 20140324
349
- 1 => $date[3].$date[0], // week like 201439
350
- 2 => $date[3].$date[2], // month like 201405
351
- 3 => $date[3], // year like 2014
352
- 4 => 'total' // total views
353
- ) as $type => $period)
354
- {
355
  if ( $using_object_cache ) {
356
  $cache_key = $id . self::CACHE_KEY_SEPARATOR . $type . self::CACHE_KEY_SEPARATOR . $period;
357
  wp_cache_add( $cache_key, 0, self::GROUP );
358
  wp_cache_incr( $cache_key, 1, self::GROUP );
359
  $cache_key_names[] = $cache_key;
360
  } else {
361
- // Hit the db directly
362
- // TODO: investigate queueing these queries on the 'shutdown' hook instead instead of running them instantly?
363
- $this->db_insert($id, $type, $period, 1);
364
  }
365
  }
366
 
367
- // Update the list of cache keys to be flushed
368
  if ( $using_object_cache && ! empty( $cache_key_names ) ) {
369
  $this->update_cached_keys_list_if_needed( $cache_key_names );
370
  }
371
 
372
- do_action('pvc_after_count_visit', $id);
373
 
374
  return true;
375
  }
376
 
377
-
378
  /**
379
- * Updates the single cache key which holds a list of all the cache keys
380
  * that need to be flushed to the db.
381
  *
382
  * The value of that special cache key is a giant string containing key names separated with the `|` character.
@@ -387,7 +383,7 @@ class Post_Views_Counter_Counter {
387
  *
388
  * This data format proved more efficient (avoids the (un)serialization overhead completely + duplicates filtering is a string search now)
389
  */
390
- private function update_cached_keys_list_if_needed($key_names = array()) {
391
  $existing_list = wp_cache_get( self::NAME_ALLKEYS, self::GROUP );
392
  if ( ! $existing_list ) {
393
  $existing_list = '';
@@ -395,14 +391,14 @@ class Post_Views_Counter_Counter {
395
 
396
  $list_modified = false;
397
 
398
- // Modifying the list contents if/when needed
399
  if ( empty( $existing_list ) ) {
400
- // The simpler case of an empty initial list where we just
401
  // transform the specified key names into a string
402
  $existing_list = implode( '|', $key_names );
403
  $list_modified = true;
404
  } else {
405
- // Searching each specified key name and appending it if it's not found
406
  foreach ( $key_names as $key_name ) {
407
  if ( false === strpos( $existing_list, $key_name ) ) {
408
  $existing_list .= '|' . $key_name;
@@ -417,12 +413,11 @@ class Post_Views_Counter_Counter {
417
  }
418
  }
419
 
420
-
421
  /**
422
- * Flushes views data stored in the persistent object cache into
423
- * our custom table and clears the object cache keys when done
424
  */
425
- public function flush_cache_to_db() {
426
  global $wpdb;
427
 
428
  $key_names = wp_cache_get( self::NAME_ALLKEYS, self::GROUP );
@@ -435,19 +430,19 @@ class Post_Views_Counter_Counter {
435
  }
436
 
437
  foreach ( $key_names as $key_name ) {
438
- // Get values stored within the key name itself
439
  list( $id, $type, $period ) = explode( self::CACHE_KEY_SEPARATOR, $key_name );
440
- // Get the cached count value
441
  $count = wp_cache_get( $key_name, self::GROUP );
442
 
443
- // Store cached value in the db
444
- $this->db_insert($id, $type, $period, $count);
445
 
446
- // Clear the cache key we just flushed
447
  wp_cache_delete( $key_name, self::GROUP );
448
  }
449
 
450
- // Delete the key holding the list itself after we've successfully flushed it
451
  if ( ! empty( $key_names ) ) {
452
  wp_cache_delete( self::NAME_ALLKEYS, self::GROUP );
453
  }
@@ -455,47 +450,44 @@ class Post_Views_Counter_Counter {
455
  return true;
456
  }
457
 
458
-
459
- private function db_insert($id, $type, $period, $count = 1) {
 
 
460
  global $wpdb;
461
 
462
  $count = (int) $count;
463
-
464
  if ( ! $count ) {
465
  $count = 1;
466
  }
467
 
468
  return $wpdb->query(
469
- $wpdb->prepare("
470
  INSERT INTO " . $wpdb->prefix . "post_views (id, type, period, count)
471
  VALUES (%d, %d, %s, %d)
472
- ON DUPLICATE KEY UPDATE count = count + %d",
473
- $id,
474
- $type,
475
- $period,
476
- $count,
477
- $count
478
- )
479
  );
480
  }
481
 
482
  /**
483
- * Checks whether visitor is a bot
484
- */
485
- private function is_robot() {
486
- if (!isset($_SERVER['HTTP_USER_AGENT']) || (isset($_SERVER['HTTP_USER_AGENT']) && trim($_SERVER['HTTP_USER_AGENT']) === ''))
487
  return false;
488
 
489
  $robots = array(
490
  'bot', 'b0t', 'Acme.Spider', 'Ahoy! The Homepage Finder', 'Alkaline', 'Anthill', 'Walhello appie', 'Arachnophilia', 'Arale', 'Araneo', 'ArchitextSpider', 'Aretha', 'ARIADNE', 'arks', 'AskJeeves', 'ASpider (Associative Spider)', 'ATN Worldwide', 'AURESYS', 'BackRub', 'Bay Spider', 'Big Brother', 'Bjaaland', 'BlackWidow', 'Die Blinde Kuh', 'Bloodhound', 'BSpider', 'CACTVS Chemistry Spider', 'Calif', 'Cassandra', 'Digimarc Marcspider/CGI', 'ChristCrawler.com', 'churl', 'cIeNcIaFiCcIoN.nEt', 'CMC/0.01', 'Collective', 'Combine System', 'Web Core / Roots', 'Cusco', 'CyberSpyder Link Test', 'CydralSpider', 'Desert Realm Spider', 'DeWeb(c) Katalog/Index', 'DienstSpider', 'Digger', 'Direct Hit Grabber', 'DownLoad Express', 'DWCP (Dridus\' Web Cataloging Project)', 'e-collector', 'EbiNess', 'Emacs-w3 Search Engine', 'ananzi', 'esculapio', 'Esther', 'Evliya Celebi', 'FastCrawler', 'Felix IDE', 'Wild Ferret Web Hopper #1, #2, #3', 'FetchRover', 'fido', 'KIT-Fireball', 'Fish search', 'Fouineur', 'Freecrawl', 'FunnelWeb', 'gammaSpider, FocusedCrawler', 'gazz', 'GCreep', 'GetURL', 'Golem', 'Grapnel/0.01 Experiment', 'Griffon', 'Gromit', 'Northern Light Gulliver', 'Harvest', 'havIndex', 'HI (HTML Index) Search', 'Hometown Spider Pro', 'ht://Dig', 'HTMLgobble', 'Hyper-Decontextualizer', 'IBM_Planetwide', 'Popular Iconoclast', 'Ingrid', 'Imagelock', 'IncyWincy', 'Informant', 'Infoseek Sidewinder', 'InfoSpiders', 'Inspector Web', 'IntelliAgent', 'Iron33', 'Israeli-search', 'JavaBee', 'JCrawler', 'Jeeves', 'JumpStation', 'image.kapsi.net', 'Katipo', 'KDD-Explorer', 'Kilroy', 'LabelGrabber', 'larbin', 'legs', 'Link Validator', 'LinkScan', 'LinkWalker', 'Lockon', 'logo.gif Crawler', 'Lycos', 'Mac WWWWorm', 'Magpie', 'marvin/infoseek', 'Mattie', 'MediaFox', 'MerzScope', 'NEC-MeshExplorer', 'MindCrawler', 'mnoGoSearch search engine software', 'moget', 'MOMspider', 'Monster', 'Motor', 'Muncher', 'Muninn', 'Muscat Ferret', 'Mwd.Search', 'Internet Shinchakubin', 'NDSpider', 'Nederland.zoek', 'NetCarta WebMap Engine', 'NetMechanic', 'NetScoop', 'newscan-online', 'NHSE Web Forager', 'Nomad', 'nzexplorer', 'ObjectsSearch', 'Occam', 'HKU WWW Octopus', 'OntoSpider', 'Openfind data gatherer', 'Orb Search', 'Pack Rat', 'PageBoy', 'ParaSite', 'Patric', 'pegasus', 'The Peregrinator', 'PerlCrawler 1.0', 'Phantom', 'PhpDig', 'PiltdownMan', 'Pioneer', 'html_analyzer', 'Portal Juice Spider', 'PGP Key Agent', 'PlumtreeWebAccessor', 'Poppi', 'PortalB Spider', 'GetterroboPlus Puu', 'Raven Search', 'RBSE Spider', 'RoadHouse Crawling System', 'ComputingSite Robi/1.0', 'RoboCrawl Spider', 'RoboFox', 'Robozilla', 'RuLeS', 'Scooter', 'Sleek', 'Search.Aus-AU.COM', 'SearchProcess', 'Senrigan', 'SG-Scout', 'ShagSeeker', 'Shai\'Hulud', 'Sift', 'Site Valet', 'SiteTech-Rover', 'Skymob.com', 'SLCrawler', 'Inktomi Slurp', 'Smart Spider', 'Snooper', 'Spanner', 'Speedy Spider', 'spider_monkey', 'Spiderline Crawler', 'SpiderMan', 'SpiderView(tm)', 'Site Searcher', 'Suke', 'suntek search engine', 'Sven', 'Sygol', 'TACH Black Widow', 'Tarantula', 'tarspider', 'Templeton', 'TeomaTechnologies', 'TITAN', 'TitIn', 'TLSpider', 'UCSD Crawl', 'UdmSearch', 'URL Check', 'URL Spider Pro', 'Valkyrie', 'Verticrawl', 'Victoria', 'vision-search', 'Voyager', 'W3M2', 'WallPaper (alias crawlpaper)', 'the World Wide Web Wanderer', 'w@pSpider by wap4.com', 'WebBandit Web Spider', 'WebCatcher', 'WebCopy', 'webfetcher', 'Webinator', 'weblayers', 'WebLinker', 'WebMirror', 'The Web Moose', 'WebQuest', 'Digimarc MarcSpider', 'WebReaper', 'webs', 'Websnarf', 'WebSpider', 'WebVac', 'webwalk', 'WebWalker', 'WebWatch', 'Wget', 'whatUseek Winona', 'Wired Digital', 'Weblog Monitor', 'w3mir', 'WebStolperer', 'The Web Wombat', 'The World Wide Web Worm', 'WWWC Ver 0.2.5', 'WebZinger', 'XGET'
491
  );
492
 
493
- foreach ($robots as $robot) {
494
- if (stripos($_SERVER['HTTP_USER_AGENT'], $robot) !== false)
495
  return true;
496
  }
497
 
498
  return false;
499
  }
 
500
  }
501
- ?>
1
  <?php
2
+ if ( ! defined( 'ABSPATH' ) )
3
+ exit;
4
 
5
  new Post_Views_Counter_Counter();
6
 
7
  class Post_Views_Counter_Counter {
8
+
9
+ const GROUP = 'pvc';
10
+ const NAME_ALLKEYS = 'cached_key_names';
11
  const CACHE_KEY_SEPARATOR = '.';
12
 
13
  private $cookie = array(
14
+ 'exists' => false,
15
+ 'visited_posts' => array(),
16
+ 'expiration' => 0
17
  );
18
 
19
  public function __construct() {
20
  // set instance
21
+ Post_Views_Counter()->add_instance( 'counter', $this );
22
 
23
  // actions
24
+ add_action( 'plugins_loaded', array( &$this, 'check_cookie' ), 1 );
25
+ add_action( 'wp', array( &$this, 'check_post' ) );
26
+ add_action( 'deleted_post', array( &$this, 'delete_post_views' ) );
27
+ add_action( 'wp_ajax_pvc-check-post', array( &$this, 'check_post_ajax' ) );
28
+ add_action( 'wp_ajax_nopriv_pvc-check-post', array( &$this, 'check_post_ajax' ) );
29
  }
30
 
31
  /**
32
+ * Remove post views from database when post is deleted.
33
+ */
34
+ public function delete_post_views( $post_id ) {
35
  global $wpdb;
36
 
37
+ $wpdb->delete( $wpdb->prefix . 'post_views', array( 'id' => $post_id ), array( '%d' ) );
38
  }
39
 
40
  /**
41
+ * Check whether user has excluded roles.
42
+ */
43
+ public function is_user_roles_excluded( $option ) {
44
  $user = wp_get_current_user();
45
 
46
+ if ( empty( $user ) )
47
  return false;
48
 
49
+ $roles = (array) $user->roles;
50
 
51
+ if ( ! empty( $roles ) ) {
52
+ foreach ( $roles as $role ) {
53
+ if ( in_array( $role, $option, true ) )
54
  return true;
55
  }
56
  }
59
  }
60
 
61
  /**
62
+ * Get timestamp convertion.
63
+ */
64
+ public function get_timestamp( $type, $number, $timestamp = true ) {
65
  $converter = array(
66
+ 'minutes' => 60,
67
+ 'hours' => 3600,
68
+ 'days' => 86400,
69
+ 'weeks' => 604800,
70
+ 'months' => 2592000,
71
+ 'years' => 946080000
72
  );
73
 
74
+ return ($timestamp ? current_time( 'timestamp', true ) : 0) + $number * $converter[$type];
75
  }
76
 
77
  /**
78
+ * Check whether to count visit via AJAX request.
79
+ */
80
  public function check_post_ajax() {
81
+ if ( isset( $_POST['action'], $_POST['post_id'], $_POST['pvc_nonce'], $_POST['post_type'] ) && $_POST['action'] === 'pvc-check-post' && ($post_id = (int) $_POST['post_id']) > 0 && wp_verify_nonce( $_POST['pvc_nonce'], 'pvc-check-post' ) !== false && Post_Views_Counter()->get_attribute( 'options', 'general', 'counter_mode' ) === 'js' ) {
82
  // get countable post types
83
+ $post_types = Post_Views_Counter()->get_attribute( 'options', 'general', 'post_types_count' );
84
 
85
  // get post type
86
+ $post_type = get_post_type( $post_id );
87
 
88
  // whether to count this post type or not
89
+ if ( empty( $post_types ) || empty( $post_type ) || $post_type !== $_POST['post_type'] || ! in_array( $post_type, $post_types, true ) )
90
  exit;
91
 
92
  // get excluded ips
93
+ $excluded_ips = Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude_ips' );
94
 
95
  // whether to count this ip or not
96
+ if ( ! empty( $excluded_ips ) && filter_var( preg_replace( '/[^0-9a-fA-F:., ]/', '', $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) && in_array( $_SERVER['REMOTE_ADDR'], $excluded_ips, true ) )
97
  exit;
98
 
99
  // get groups to check them faster
100
+ $groups = Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude', 'groups' );
101
 
102
  // whether to count this user
103
+ if ( is_user_logged_in() ) {
104
  // exclude logged in users?
105
+ if ( in_array( 'users', $groups, true ) )
106
  exit;
107
  // exclude specific roles?
108
+ elseif ( in_array( 'roles', $groups, true ) && $this->is_user_roles_excluded( Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude', 'roles' ) ) )
109
  exit;
110
  }
111
  // exclude guests?
112
+ elseif ( in_array( 'guests', $groups, true ) )
113
  exit;
114
 
115
  // whether to count robots
116
+ if ( $this->is_robot() )
117
  exit;
118
 
119
  // cookie already existed?
120
+ if ( $this->cookie['exists'] ) {
121
  // post already viewed but not expired?
122
+ if ( in_array( $post_id, array_keys( $this->cookie['visited_posts'] ), true ) && current_time( 'timestamp', true ) < $this->cookie['visited_posts'][$post_id] ) {
123
  // updates cookie but do not count visit
124
+ $this->save_cookie( $post_id, $this->cookie, false );
125
 
126
  exit;
127
+ } else
128
+ // updates cookie
129
+ $this->save_cookie( $post_id, $this->cookie );
 
130
  } else {
131
  // set new cookie
132
+ $this->save_cookie( $post_id );
133
  }
134
 
135
  // count visit
136
+ $this->count_visit( $post_id );
137
  }
138
 
139
  exit;
140
  }
141
 
142
  /**
143
+ * Check whether to count visit.
144
+ */
145
  public function check_post() {
146
  // do not count admin entries
147
+ if ( is_admin() )
148
  return;
149
 
150
  // do we use PHP as counter?
151
+ if ( Post_Views_Counter()->get_attribute( 'options', 'general', 'counter_mode' ) === 'php' ) {
152
+ $post_types = Post_Views_Counter()->get_attribute( 'options', 'general', 'post_types_count' );
153
 
154
  // whether to count this post type
155
+ if ( empty( $post_types ) || ! is_singular( $post_types ) )
156
  return;
157
 
158
+ $ips = Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude_ips' );
159
 
160
  // whether to count this ip
161
+ if ( ! empty( $ips ) && filter_var( preg_replace( '/[^0-9a-fA-F:., ]/', '', $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) && in_array( $_SERVER['REMOTE_ADDR'], $ips, true ) )
162
  return;
163
 
164
  // get groups to check them faster
165
+ $groups = Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude', 'groups' );
166
 
167
  // whether to count this user
168
+ if ( is_user_logged_in() ) {
169
  // exclude logged in users?
170
+ if ( in_array( 'users', $groups, true ) )
171
  return;
172
  // exclude specific roles?
173
+ elseif ( in_array( 'roles', $groups, true ) && $this->is_user_roles_excluded( Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude', 'roles' ) ) )
174
  return;
175
  }
176
  // exclude guests?
177
+ elseif ( in_array( 'guests', $groups, true ) )
178
  return;
179
 
180
  // whether to count robots
181
+ if ( $this->is_robot() )
182
  return;
183
 
184
  // get post id
185
  $id = get_the_ID();
186
 
187
  // cookie already existed?
188
+ if ( $this->cookie['exists'] ) {
189
  // post already viewed but not expired?
190
+ if ( in_array( $id, array_keys( $this->cookie['visited_posts'] ), true ) && current_time( 'timestamp', true ) < $this->cookie['visited_posts'][$id] ) {
191
  // update cookie but do not count visit
192
+ $this->save_cookie( $id, $this->cookie, false );
193
 
194
  return;
195
+ } else
196
+ // update cookie
197
+ $this->save_cookie( $id, $this->cookie );
198
+ } else
199
+ // set new cookie
200
+ $this->save_cookie( $id );
 
 
201
 
202
  // count visit
203
+ $this->count_visit( $id );
204
  }
205
  }
206
 
207
  /**
208
+ * Initialize cookie session.
209
+ */
210
  public function check_cookie() {
211
  // do not run in admin except for ajax requests
212
+ if ( is_admin() && ! (defined( 'DOING_AJAX' ) && DOING_AJAX) )
213
  return;
214
 
215
  // is cookie set?
216
+ if ( isset( $_COOKIE['pvc_visits'] ) && ! empty( $_COOKIE['pvc_visits'] ) ) {
217
  $visited_posts = $expirations = array();
218
 
219
+ foreach ( $_COOKIE['pvc_visits'] as $content ) {
220
  // is cookie valid?
221
+ if ( preg_match( '/^(([0-9]+b[0-9]+a?)+)$/', $content ) === 1 ) {
222
  // get single id with expiration
223
+ $expiration_ids = explode( 'a', $content );
224
 
225
  // check every expiration => id pair
226
+ foreach ( $expiration_ids as $pair ) {
227
+ $pair = explode( 'b', $pair );
228
+ $expirations[] = (int) $pair[0];
229
+ $visited_posts[(int) $pair[1]] = (int) $pair[0];
230
  }
231
  }
232
  }
233
 
234
  $this->cookie = array(
235
+ 'exists' => true,
236
+ 'visited_posts' => $visited_posts,
237
+ 'expiration' => max( $expirations )
238
  );
239
  }
240
  }
241
 
242
  /**
243
+ * Save cookie function.
244
+ */
245
+ private function save_cookie( $id, $cookie = array(), $expired = true ) {
246
+ $expiration = $this->get_timestamp( Post_Views_Counter()->get_attribute( 'options', 'general', 'time_between_counts', 'type' ), Post_Views_Counter()->get_attribute( 'options', 'general', 'time_between_counts', 'number' ) );
247
 
248
  // is this a new cookie?
249
+ if ( empty( $cookie ) ) {
250
  // set cookie
251
+ setcookie( 'pvc_visits[0]', $expiration . 'b' . $id, $expiration, COOKIEPATH, COOKIE_DOMAIN, (isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ? true : false ), true );
252
  } else {
253
+ if ( $expired ) {
254
  // add new id or chang expiration date if id already exists
255
  $cookie['visited_posts'][$id] = $expiration;
256
  }
259
  $visited_posts_expirations = $cookie['visited_posts'];
260
 
261
  // get current gmt time
262
+ $time = current_time( 'timestamp', true );
263
 
264
  // check whether viewed id has expired - no need to keep it in cookie (less size)
265
+ foreach ( $visited_posts_expirations as $post_id => $post_expiration ) {
266
+ if ( $time > $post_expiration )
267
+ unset( $cookie['visited_posts'][$post_id] );
268
  }
269
 
270
  // set new last expiration date if needed
271
+ $cookie['expiration'] = max( $cookie['visited_posts'] );
272
 
273
  $cookies = $imploded = array();
274
 
275
  // create pairs
276
+ foreach ( $cookie['visited_posts'] as $id => $exp ) {
277
+ $imploded[] = $exp . 'b' . $id;
278
  }
279
 
280
  // split cookie into chunks (4000 bytes to make sure it is safe for every browser)
281
+ $chunks = str_split( implode( 'a', $imploded ), 4000 );
282
 
283
  // more then one chunk?
284
+ if ( count( $chunks ) > 1 ) {
285
  $last_id = '';
286
 
287
+ foreach ( $chunks as $chunk_id => $chunk ) {
288
  // new chunk
289
+ $chunk_c = $last_id . $chunk;
290
 
291
  // is it full-length chunk?
292
+ if ( strlen( $chunk ) === 4000 ) {
293
  // get last part
294
+ $last_part = strrchr( $chunk_c, 'a' );
295
 
296
  // get last id
297
+ $last_id = substr( $last_part, 1 );
298
 
299
  // add new full-lenght chunk
300
+ $cookies[$chunk_id] = substr( $chunk_c, 0, strlen( $chunk_c ) - strlen( $last_part ) );
301
  } else {
302
  // add last chunk
303
  $cookies[$chunk_id] = $chunk_c;
304
  }
305
  }
 
306
  } else {
307
  // only one chunk
308
  $cookies[] = $chunks[0];
309
  }
310
 
311
+ foreach ( $cookies as $key => $value ) {
312
  // set cookie
313
+ setcookie( 'pvc_visits[' . $key . ']', $value, $cookie['expiration'], COOKIEPATH, COOKIE_DOMAIN, (isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ? true : false ), true );
314
  }
315
  }
316
  }
317
 
318
+ /**
319
+ * Check if object cache is in use.
320
+ */
321
+ public function using_object_cache( $using = null ) {
322
  $using = wp_using_ext_object_cache( $using );
323
 
324
  if ( $using ) {
325
+ // check if explicitly disabled by flush_interval setting/option <= 0
326
+ $flush_interval_number = Post_Views_Counter()->get_attribute( 'options', 'general', 'flush_interval', 'number' );
327
  $using = ( $flush_interval_number <= 0 ) ? false : true;
328
  }
329
 
330
  return $using;
331
  }
332
 
 
333
  /**
334
+ * Count visit function.
335
+ */
336
+ private function count_visit( $id ) {
337
  global $wpdb;
338
 
339
+ $cache_key_names = array();
340
  $using_object_cache = $this->using_object_cache();
341
 
342
+ // get day, week, month and year
343
+ $date = explode( '-', date( 'W-d-m-Y', current_time( 'timestamp' ) ) );
344
+
345
+ foreach ( array(
346
+ 0 => $date[3] . $date[2] . $date[1], // day like 20140324
347
+ 1 => $date[3] . $date[0], // week like 201439
348
+ 2 => $date[3] . $date[2], // month like 201405
349
+ 3 => $date[3], // year like 2014
350
+ 4 => 'total' // total views
351
+ ) as $type => $period ) {
 
352
  if ( $using_object_cache ) {
353
  $cache_key = $id . self::CACHE_KEY_SEPARATOR . $type . self::CACHE_KEY_SEPARATOR . $period;
354
  wp_cache_add( $cache_key, 0, self::GROUP );
355
  wp_cache_incr( $cache_key, 1, self::GROUP );
356
  $cache_key_names[] = $cache_key;
357
  } else {
358
+ // hit the db directly
359
+ // @TODO: investigate queueing these queries on the 'shutdown' hook instead instead of running them instantly?
360
+ $this->db_insert( $id, $type, $period, 1 );
361
  }
362
  }
363
 
364
+ // update the list of cache keys to be flushed
365
  if ( $using_object_cache && ! empty( $cache_key_names ) ) {
366
  $this->update_cached_keys_list_if_needed( $cache_key_names );
367
  }
368
 
369
+ do_action( 'pvc_after_count_visit', $id );
370
 
371
  return true;
372
  }
373
 
 
374
  /**
375
+ * Update the single cache key which holds a list of all the cache keys
376
  * that need to be flushed to the db.
377
  *
378
  * The value of that special cache key is a giant string containing key names separated with the `|` character.
383
  *
384
  * This data format proved more efficient (avoids the (un)serialization overhead completely + duplicates filtering is a string search now)
385
  */
386
+ private function update_cached_keys_list_if_needed( $key_names = array() ) {
387
  $existing_list = wp_cache_get( self::NAME_ALLKEYS, self::GROUP );
388
  if ( ! $existing_list ) {
389
  $existing_list = '';
391
 
392
  $list_modified = false;
393
 
394
+ // modify the list contents if/when needed
395
  if ( empty( $existing_list ) ) {
396
+ // the simpler case of an empty initial list where we just
397
  // transform the specified key names into a string
398
  $existing_list = implode( '|', $key_names );
399
  $list_modified = true;
400
  } else {
401
+ // search each specified key name and append it if it's not found
402
  foreach ( $key_names as $key_name ) {
403
  if ( false === strpos( $existing_list, $key_name ) ) {
404
  $existing_list .= '|' . $key_name;
413
  }
414
  }
415
 
 
416
  /**
417
+ * Flush views data stored in the persistent object cache into
418
+ * our custom table and clear the object cache keys when done
419
  */
420
+ public function flush_cache_to_db() {
421
  global $wpdb;
422
 
423
  $key_names = wp_cache_get( self::NAME_ALLKEYS, self::GROUP );
430
  }
431
 
432
  foreach ( $key_names as $key_name ) {
433
+ // get values stored within the key name itself
434
  list( $id, $type, $period ) = explode( self::CACHE_KEY_SEPARATOR, $key_name );
435
+ // get the cached count value
436
  $count = wp_cache_get( $key_name, self::GROUP );
437
 
438
+ // store cached value in the db
439
+ $this->db_insert( $id, $type, $period, $count );
440
 
441
+ // clear the cache key we just flushed
442
  wp_cache_delete( $key_name, self::GROUP );
443
  }
444
 
445
+ // delete the key holding the list itself after we've successfully flushed it
446
  if ( ! empty( $key_names ) ) {
447
  wp_cache_delete( self::NAME_ALLKEYS, self::GROUP );
448
  }
450
  return true;
451
  }
452
 
453
+ /*
454
+ * Insert or update views count.
455
+ */
456
+ private function db_insert( $id, $type, $period, $count = 1 ) {
457
  global $wpdb;
458
 
459
  $count = (int) $count;
460
+
461
  if ( ! $count ) {
462
  $count = 1;
463
  }
464
 
465
  return $wpdb->query(
466
+ $wpdb->prepare( "
467
  INSERT INTO " . $wpdb->prefix . "post_views (id, type, period, count)
468
  VALUES (%d, %d, %s, %d)
469
+ ON DUPLICATE KEY UPDATE count = count + %d", $id, $type, $period, $count, $count
470
+ )
 
 
 
 
 
471
  );
472
  }
473
 
474
  /**
475
+ * Check whether visitor is a bot.
476
+ */
477
+ private function is_robot() {
478
+ if ( ! isset( $_SERVER['HTTP_USER_AGENT'] ) || (isset( $_SERVER['HTTP_USER_AGENT'] ) && trim( $_SERVER['HTTP_USER_AGENT'] ) === '') )
479
  return false;
480
 
481
  $robots = array(
482
  'bot', 'b0t', 'Acme.Spider', 'Ahoy! The Homepage Finder', 'Alkaline', 'Anthill', 'Walhello appie', 'Arachnophilia', 'Arale', 'Araneo', 'ArchitextSpider', 'Aretha', 'ARIADNE', 'arks', 'AskJeeves', 'ASpider (Associative Spider)', 'ATN Worldwide', 'AURESYS', 'BackRub', 'Bay Spider', 'Big Brother', 'Bjaaland', 'BlackWidow', 'Die Blinde Kuh', 'Bloodhound', 'BSpider', 'CACTVS Chemistry Spider', 'Calif', 'Cassandra', 'Digimarc Marcspider/CGI', 'ChristCrawler.com', 'churl', 'cIeNcIaFiCcIoN.nEt', 'CMC/0.01', 'Collective', 'Combine System', 'Web Core / Roots', 'Cusco', 'CyberSpyder Link Test', 'CydralSpider', 'Desert Realm Spider', 'DeWeb(c) Katalog/Index', 'DienstSpider', 'Digger', 'Direct Hit Grabber', 'DownLoad Express', 'DWCP (Dridus\' Web Cataloging Project)', 'e-collector', 'EbiNess', 'Emacs-w3 Search Engine', 'ananzi', 'esculapio', 'Esther', 'Evliya Celebi', 'FastCrawler', 'Felix IDE', 'Wild Ferret Web Hopper #1, #2, #3', 'FetchRover', 'fido', 'KIT-Fireball', 'Fish search', 'Fouineur', 'Freecrawl', 'FunnelWeb', 'gammaSpider, FocusedCrawler', 'gazz', 'GCreep', 'GetURL', 'Golem', 'Grapnel/0.01 Experiment', 'Griffon', 'Gromit', 'Northern Light Gulliver', 'Harvest', 'havIndex', 'HI (HTML Index) Search', 'Hometown Spider Pro', 'ht://Dig', 'HTMLgobble', 'Hyper-Decontextualizer', 'IBM_Planetwide', 'Popular Iconoclast', 'Ingrid', 'Imagelock', 'IncyWincy', 'Informant', 'Infoseek Sidewinder', 'InfoSpiders', 'Inspector Web', 'IntelliAgent', 'Iron33', 'Israeli-search', 'JavaBee', 'JCrawler', 'Jeeves', 'JumpStation', 'image.kapsi.net', 'Katipo', 'KDD-Explorer', 'Kilroy', 'LabelGrabber', 'larbin', 'legs', 'Link Validator', 'LinkScan', 'LinkWalker', 'Lockon', 'logo.gif Crawler', 'Lycos', 'Mac WWWWorm', 'Magpie', 'marvin/infoseek', 'Mattie', 'MediaFox', 'MerzScope', 'NEC-MeshExplorer', 'MindCrawler', 'mnoGoSearch search engine software', 'moget', 'MOMspider', 'Monster', 'Motor', 'Muncher', 'Muninn', 'Muscat Ferret', 'Mwd.Search', 'Internet Shinchakubin', 'NDSpider', 'Nederland.zoek', 'NetCarta WebMap Engine', 'NetMechanic', 'NetScoop', 'newscan-online', 'NHSE Web Forager', 'Nomad', 'nzexplorer', 'ObjectsSearch', 'Occam', 'HKU WWW Octopus', 'OntoSpider', 'Openfind data gatherer', 'Orb Search', 'Pack Rat', 'PageBoy', 'ParaSite', 'Patric', 'pegasus', 'The Peregrinator', 'PerlCrawler 1.0', 'Phantom', 'PhpDig', 'PiltdownMan', 'Pioneer', 'html_analyzer', 'Portal Juice Spider', 'PGP Key Agent', 'PlumtreeWebAccessor', 'Poppi', 'PortalB Spider', 'GetterroboPlus Puu', 'Raven Search', 'RBSE Spider', 'RoadHouse Crawling System', 'ComputingSite Robi/1.0', 'RoboCrawl Spider', 'RoboFox', 'Robozilla', 'RuLeS', 'Scooter', 'Sleek', 'Search.Aus-AU.COM', 'SearchProcess', 'Senrigan', 'SG-Scout', 'ShagSeeker', 'Shai\'Hulud', 'Sift', 'Site Valet', 'SiteTech-Rover', 'Skymob.com', 'SLCrawler', 'Inktomi Slurp', 'Smart Spider', 'Snooper', 'Spanner', 'Speedy Spider', 'spider_monkey', 'Spiderline Crawler', 'SpiderMan', 'SpiderView(tm)', 'Site Searcher', 'Suke', 'suntek search engine', 'Sven', 'Sygol', 'TACH Black Widow', 'Tarantula', 'tarspider', 'Templeton', 'TeomaTechnologies', 'TITAN', 'TitIn', 'TLSpider', 'UCSD Crawl', 'UdmSearch', 'URL Check', 'URL Spider Pro', 'Valkyrie', 'Verticrawl', 'Victoria', 'vision-search', 'Voyager', 'W3M2', 'WallPaper (alias crawlpaper)', 'the World Wide Web Wanderer', 'w@pSpider by wap4.com', 'WebBandit Web Spider', 'WebCatcher', 'WebCopy', 'webfetcher', 'Webinator', 'weblayers', 'WebLinker', 'WebMirror', 'The Web Moose', 'WebQuest', 'Digimarc MarcSpider', 'WebReaper', 'webs', 'Websnarf', 'WebSpider', 'WebVac', 'webwalk', 'WebWalker', 'WebWatch', 'Wget', 'whatUseek Winona', 'Wired Digital', 'Weblog Monitor', 'w3mir', 'WebStolperer', 'The Web Wombat', 'The World Wide Web Worm', 'WWWC Ver 0.2.5', 'WebZinger', 'XGET'
483
  );
484
 
485
+ foreach ( $robots as $robot ) {
486
+ if ( stripos( $_SERVER['HTTP_USER_AGENT'], $robot ) !== false )
487
  return true;
488
  }
489
 
490
  return false;
491
  }
492
+
493
  }
 
includes/cron.php CHANGED
@@ -1,99 +1,96 @@
1
  <?php
2
- if(!defined('ABSPATH')) exit;
 
3
 
4
  new Post_Views_Counter_Cron();
5
 
6
  class Post_Views_Counter_Cron {
7
-
8
  public function __construct() {
9
  // set instance
10
- Post_Views_Counter()->add_instance('cron', $this);
11
 
12
  // actions
13
- add_action('init', array(&$this, 'check_cron'));
14
- add_action('pvc_reset_counts', array(&$this, 'reset_counts'));
15
- add_action('pvc_flush_cached_counts', array(&$this, 'flush_cached_counts'));
16
 
17
  // filters
18
- add_filter('cron_schedules', array(&$this, 'cron_time_intervals'));
19
  }
20
 
21
-
22
  /**
23
- * Reset daily counts
24
- */
25
  public function reset_counts() {
26
  global $wpdb;
27
 
28
- $wpdb->query('DELETE FROM '.$wpdb->prefix.'post_views WHERE type = 0');
29
  }
30
 
31
-
32
  /**
33
- * Call Post_Views_Counter_Counter::flush_cache_to_db()
34
- * This is (un)scheduled on plugin activation/deactivation
35
  */
36
  public function flush_cached_counts() {
37
- $counter = Post_Views_Counter()->get_instance('counter');
38
-
39
  if ( $counter && $counter->using_object_cache() ) {
40
  $counter->flush_cache_to_db();
41
  }
42
  }
43
 
44
-
45
  /**
46
- * Add new cron interval from settings
47
- */
48
- public function cron_time_intervals($schedules) {
49
  $schedules['post_views_counter_interval'] = array(
50
- 'interval' => Post_Views_Counter()->get_instance('counter')->get_timestamp(Post_Views_Counter()->get_attribute('options', 'general', 'reset_counts', 'type'), Post_Views_Counter()->get_attribute('options', 'general', 'reset_counts', 'number'), false),
51
- 'display' => __('Post Views Counter reset daily counts interval', 'post-views-counter')
52
  );
53
 
54
  $schedules['post_views_counter_flush_interval'] = array(
55
- 'interval' => Post_Views_Counter()->get_instance('counter')->get_timestamp(Post_Views_Counter()->get_attribute('options', 'general', 'flush_interval', 'type'), Post_Views_Counter()->get_attribute('options', 'general', 'flush_interval', 'number'), false),
56
- 'display' => __('Post Views Counter cache flush interval', 'post-views-counter')
57
  );
58
 
59
  return $schedules;
60
  }
61
 
62
-
63
  /**
64
- * Check whether WP Cron needs to add new task
65
- */
66
  public function check_cron() {
67
- if (!is_admin())
68
  return;
69
 
70
- // sets wp cron task
71
- if (Post_Views_Counter()->get_attribute('options', 'general', 'cron_run')) {
72
 
73
  // not set or need to be updated?
74
- if (!wp_next_scheduled('pvc_reset_counts') || Post_Views_Counter()->get_attribute('options', 'general', 'cron_update')) {
75
-
76
  // task is added but need to be updated
77
- if (Post_Views_Counter()->get_attribute('options', 'general', 'cron_update')) {
78
  // remove old schedule
79
- wp_clear_scheduled_hook('pvc_reset_counts');
80
 
81
  // set update to false
82
- $general = Post_Views_Counter()->get_attribute('options', 'general');
83
  $general['cron_update'] = false;
84
 
85
  // update settings
86
- update_option('post_views_counter_settings_general', $general);
87
  }
88
 
89
  // set schedule
90
- wp_schedule_event(Post_Views_Counter()->get_instance('counter')->get_timestamp(Post_Views_Counter()->get_attribute('options', 'general', 'reset_counts', 'type'), Post_Views_Counter()->get_attribute('options', 'general', 'reset_counts', 'number')), 'post_views_counter_interval', 'pvc_reset_counts');
91
  }
92
  } else {
93
  // remove schedule
94
- wp_clear_scheduled_hook('pvc_reset_counts');
95
- remove_action('pvc_reset_counts', array(&$this, 'reset_counts'));
96
  }
97
  }
 
98
  }
99
- ?>
1
  <?php
2
+ if ( ! defined( 'ABSPATH' ) )
3
+ exit;
4
 
5
  new Post_Views_Counter_Cron();
6
 
7
  class Post_Views_Counter_Cron {
8
+
9
  public function __construct() {
10
  // set instance
11
+ Post_Views_Counter()->add_instance( 'cron', $this );
12
 
13
  // actions
14
+ add_action( 'init', array( &$this, 'check_cron' ) );
15
+ add_action( 'pvc_reset_counts', array( &$this, 'reset_counts' ) );
16
+ add_action( 'pvc_flush_cached_counts', array( &$this, 'flush_cached_counts' ) );
17
 
18
  // filters
19
+ add_filter( 'cron_schedules', array( &$this, 'cron_time_intervals' ) );
20
  }
21
 
 
22
  /**
23
+ * Reset daily counts.
24
+ */
25
  public function reset_counts() {
26
  global $wpdb;
27
 
28
+ $wpdb->query( 'DELETE FROM ' . $wpdb->prefix . 'post_views WHERE type = 0' );
29
  }
30
 
 
31
  /**
32
+ * Call Post_Views_Counter_Counter::flush_cache_to_db().
33
+ * This is (un)scheduled on plugin activation/deactivation.
34
  */
35
  public function flush_cached_counts() {
36
+ $counter = Post_Views_Counter()->get_instance( 'counter' );
37
+
38
  if ( $counter && $counter->using_object_cache() ) {
39
  $counter->flush_cache_to_db();
40
  }
41
  }
42
 
 
43
  /**
44
+ * Add new cron interval from settings.
45
+ */
46
+ public function cron_time_intervals( $schedules ) {
47
  $schedules['post_views_counter_interval'] = array(
48
+ 'interval' => Post_Views_Counter()->get_instance( 'counter' )->get_timestamp( Post_Views_Counter()->get_attribute( 'options', 'general', 'reset_counts', 'type' ), Post_Views_Counter()->get_attribute( 'options', 'general', 'reset_counts', 'number' ), false ),
49
+ 'display' => __( 'Post Views Counter reset daily counts interval', 'post-views-counter' )
50
  );
51
 
52
  $schedules['post_views_counter_flush_interval'] = array(
53
+ 'interval' => Post_Views_Counter()->get_instance( 'counter' )->get_timestamp( Post_Views_Counter()->get_attribute( 'options', 'general', 'flush_interval', 'type' ), Post_Views_Counter()->get_attribute( 'options', 'general', 'flush_interval', 'number' ), false ),
54
+ 'display' => __( 'Post Views Counter cache flush interval', 'post-views-counter' )
55
  );
56
 
57
  return $schedules;
58
  }
59
 
 
60
  /**
61
+ * Check whether WP Cron needs to add new task.
62
+ */
63
  public function check_cron() {
64
+ if ( ! is_admin() )
65
  return;
66
 
67
+ // set wp cron task
68
+ if ( Post_Views_Counter()->get_attribute( 'options', 'general', 'cron_run' ) ) {
69
 
70
  // not set or need to be updated?
71
+ if ( ! wp_next_scheduled( 'pvc_reset_counts' ) || Post_Views_Counter()->get_attribute( 'options', 'general', 'cron_update' ) ) {
72
+
73
  // task is added but need to be updated
74
+ if ( Post_Views_Counter()->get_attribute( 'options', 'general', 'cron_update' ) ) {
75
  // remove old schedule
76
+ wp_clear_scheduled_hook( 'pvc_reset_counts' );
77
 
78
  // set update to false
79
+ $general = Post_Views_Counter()->get_attribute( 'options', 'general' );
80
  $general['cron_update'] = false;
81
 
82
  // update settings
83
+ update_option( 'post_views_counter_settings_general', $general );
84
  }
85
 
86
  // set schedule
87
+ wp_schedule_event( Post_Views_Counter()->get_instance( 'counter' )->get_timestamp( Post_Views_Counter()->get_attribute( 'options', 'general', 'reset_counts', 'type' ), Post_Views_Counter()->get_attribute( 'options', 'general', 'reset_counts', 'number' ) ), 'post_views_counter_interval', 'pvc_reset_counts' );
88
  }
89
  } else {
90
  // remove schedule
91
+ wp_clear_scheduled_hook( 'pvc_reset_counts' );
92
+ remove_action( 'pvc_reset_counts', array( &$this, 'reset_counts' ) );
93
  }
94
  }
95
+
96
  }
 
includes/frontend.php CHANGED
@@ -1,5 +1,6 @@
1
  <?php
2
- if(!defined('ABSPATH')) exit;
 
3
 
4
  new Post_Views_Counter_Frontend();
5
 
@@ -7,62 +8,62 @@ class Post_Views_Counter_Frontend {
7
 
8
  public function __construct() {
9
  // actions
10
- add_action('wp_loaded', array(&$this, 'register_shortcode'));
11
- add_action('wp_enqueue_scripts', array(&$this, 'frontend_scripts_styles'));
12
 
13
  // filters
14
- add_filter('the_content', array(&$this, 'add_post_views_count'));
15
- add_filter('the_excerpt', array(&$this, 'remove_post_views_count'));
16
  }
17
 
18
  /**
19
- * Register post-views shortcode function
20
- */
21
  public function register_shortcode() {
22
- add_shortcode('post-views', array(&$this, 'post_views_shortcode'));
23
  }
24
 
25
  /**
26
- * Post views shortcode function
27
- */
28
- public function post_views_shortcode($args) {
29
  $defaults = array(
30
  'id' => get_the_ID()
31
  );
32
 
33
- $args = shortcode_atts($defaults, $args);
34
 
35
- return pvc_post_views($args['id'], false);
36
  }
37
 
38
  /**
39
- * Add post views counter to content
40
- */
41
- public function add_post_views_count($content) {
42
- if (is_singular() && in_array(get_post_type(), Post_Views_Counter()->get_attribute('options', 'display', 'post_types_display'), true)) {
43
-
44
  // get groups to check it faster
45
- $groups = Post_Views_Counter()->get_attribute('options', 'display', 'restrict_display', 'groups');
46
 
47
  // whether to display views
48
- if (is_user_logged_in()) {
49
  // exclude logged in users?
50
- if(in_array('users', $groups, true))
51
  return $content;
52
  // exclude specific roles?
53
- elseif(in_array('roles', $groups, true) && Post_Views_Counter()->get_instance('counter')->is_user_roles_excluded(Post_Views_Counter()->get_attribute('options', 'display', 'restrict_display', 'roles')))
54
  return $content;
55
  }
56
  // exclude guests?
57
- elseif (in_array('guests', $groups, true))
58
  return $content;
59
 
60
- switch (Post_Views_Counter()->get_attribute('options', 'display', 'position')) {
61
  case 'after':
62
- return $content.'[post-views]';
63
 
64
  case 'before':
65
- return '[post-views]'.$content;
66
 
67
  default:
68
  case 'manual':
@@ -72,58 +73,53 @@ class Post_Views_Counter_Frontend {
72
 
73
  return $content;
74
  }
75
-
76
  /**
77
- * Remove post views shortcode from excerpt
78
- */
79
- public function remove_post_views_count($excerpt) {
80
- remove_shortcode('post-views');
81
- $excerpt = preg_replace ('/\[post-views[^\]]*\]/', '', $excerpt);
82
  return $excerpt;
83
  }
84
-
85
  /**
86
- * Enqueue frontend scripts and styles
87
- */
88
  public function frontend_scripts_styles() {
89
- $post_types = Post_Views_Counter()->get_attribute('options', 'display', 'post_types_display');
90
 
91
  // load dashicons
92
- wp_enqueue_style('dashicons');
93
-
94
  wp_register_style(
95
- 'post-views-counter-frontend',
96
- POST_VIEWS_COUNTER_URL.'/css/frontend.css'
97
  );
98
-
99
- wp_enqueue_style('post-views-counter-frontend');
100
 
101
- if (Post_Views_Counter()->get_attribute('options', 'general', 'counter_mode') === 'js') {
102
- $post_types = Post_Views_Counter()->get_attribute('options', 'general', 'post_types_count');
 
 
103
 
104
  // whether to count this post type or not
105
- if (empty($post_types) || !is_singular($post_types))
106
  return;
107
 
108
  wp_register_script(
109
- 'post-views-counter-frontend',
110
- POST_VIEWS_COUNTER_URL.'/js/frontend.js',
111
- array('jquery')
112
  );
113
 
114
- wp_enqueue_script('post-views-counter-frontend');
115
 
116
  wp_localize_script(
117
- 'post-views-counter-frontend',
118
- 'pvcArgsFrontend',
119
- array(
120
- 'ajaxURL' => admin_url('admin-ajax.php'),
121
- 'postID' => get_the_ID(),
122
- 'nonce' => wp_create_nonce('pvc-check-post'),
123
- 'postType' => get_post_type()
124
  )
125
  );
126
  }
127
  }
 
128
  }
129
- ?>
1
  <?php
2
+ if ( ! defined( 'ABSPATH' ) )
3
+ exit;
4
 
5
  new Post_Views_Counter_Frontend();
6
 
8
 
9
  public function __construct() {
10
  // actions
11
+ add_action( 'wp_loaded', array( &$this, 'register_shortcode' ) );
12
+ add_action( 'wp_enqueue_scripts', array( &$this, 'frontend_scripts_styles' ) );
13
 
14
  // filters
15
+ add_filter( 'the_content', array( &$this, 'add_post_views_count' ) );
16
+ add_filter( 'the_excerpt', array( &$this, 'remove_post_views_count' ) );
17
  }
18
 
19
  /**
20
+ * Register post-views shortcode function.
21
+ */
22
  public function register_shortcode() {
23
+ add_shortcode( 'post-views', array( &$this, 'post_views_shortcode' ) );
24
  }
25
 
26
  /**
27
+ * Post views shortcode function.
28
+ */
29
+ public function post_views_shortcode( $args ) {
30
  $defaults = array(
31
  'id' => get_the_ID()
32
  );
33
 
34
+ $args = shortcode_atts( $defaults, $args );
35
 
36
+ return pvc_post_views( $args['id'], false );
37
  }
38
 
39
  /**
40
+ * Add post views counter to content.
41
+ */
42
+ public function add_post_views_count( $content ) {
43
+ if ( is_singular() && in_array( get_post_type(), Post_Views_Counter()->get_attribute( 'options', 'display', 'post_types_display' ), true ) ) {
44
+
45
  // get groups to check it faster
46
+ $groups = Post_Views_Counter()->get_attribute( 'options', 'display', 'restrict_display', 'groups' );
47
 
48
  // whether to display views
49
+ if ( is_user_logged_in() ) {
50
  // exclude logged in users?
51
+ if ( in_array( 'users', $groups, true ) )
52
  return $content;
53
  // exclude specific roles?
54
+ elseif ( in_array( 'roles', $groups, true ) && Post_Views_Counter()->get_instance( 'counter' )->is_user_roles_excluded( Post_Views_Counter()->get_attribute( 'options', 'display', 'restrict_display', 'roles' ) ) )
55
  return $content;
56
  }
57
  // exclude guests?
58
+ elseif ( in_array( 'guests', $groups, true ) )
59
  return $content;
60
 
61
+ switch ( Post_Views_Counter()->get_attribute( 'options', 'display', 'position' ) ) {
62
  case 'after':
63
+ return $content . '[post-views]';
64
 
65
  case 'before':
66
+ return '[post-views]' . $content;
67
 
68
  default:
69
  case 'manual':
73
 
74
  return $content;
75
  }
76
+
77
  /**
78
+ * Remove post views shortcode from excerpt.
79
+ */
80
+ public function remove_post_views_count( $excerpt ) {
81
+ remove_shortcode( 'post-views' );
82
+ $excerpt = preg_replace( '/\[post-views[^\]]*\]/', '', $excerpt );
83
  return $excerpt;
84
  }
85
+
86
  /**
87
+ * Enqueue frontend scripts and styles.
88
+ */
89
  public function frontend_scripts_styles() {
90
+ $post_types = Post_Views_Counter()->get_attribute( 'options', 'display', 'post_types_display' );
91
 
92
  // load dashicons
93
+ wp_enqueue_style( 'dashicons' );
94
+
95
  wp_register_style(
96
+ 'post-views-counter-frontend', POST_VIEWS_COUNTER_URL . '/css/frontend.css'
 
97
  );
 
 
98
 
99
+ wp_enqueue_style( 'post-views-counter-frontend' );
100
+
101
+ if ( Post_Views_Counter()->get_attribute( 'options', 'general', 'counter_mode' ) === 'js' ) {
102
+ $post_types = Post_Views_Counter()->get_attribute( 'options', 'general', 'post_types_count' );
103
 
104
  // whether to count this post type or not
105
+ if ( empty( $post_types ) || ! is_singular( $post_types ) )
106
  return;
107
 
108
  wp_register_script(
109
+ 'post-views-counter-frontend', POST_VIEWS_COUNTER_URL . '/js/frontend.js', array( 'jquery' )
 
 
110
  );
111
 
112
+ wp_enqueue_script( 'post-views-counter-frontend' );
113
 
114
  wp_localize_script(
115
+ 'post-views-counter-frontend', 'pvcArgsFrontend', array(
116
+ 'ajaxURL' => admin_url( 'admin-ajax.php' ),
117
+ 'postID' => get_the_ID(),
118
+ 'nonce' => wp_create_nonce( 'pvc-check-post' ),
119
+ 'postType' => get_post_type()
 
 
120
  )
121
  );
122
  }
123
  }
124
+
125
  }
 
includes/functions.php CHANGED
@@ -9,171 +9,173 @@
9
  * @since 1.0.0
10
  */
11
 
12
- if (!defined('ABSPATH')) exit;
 
13
 
14
  /**
15
- * Get post views for a post or array of posts
16
  *
17
  * @param int|array $post_id
18
  * @return int
19
  */
20
- if (!function_exists('pvc_get_post_views')) {
21
- function pvc_get_post_views($post_id = 0) {
22
- if (empty($post_id))
 
23
  $post_id = get_the_ID();
24
 
25
- if (is_array($post_id))
26
- $post_id = implode(',', array_map('intval', $post_id));
27
  else
28
- $post_id = (int)$post_id;
29
 
30
  global $wpdb;
31
 
32
- $post_views = (int)$wpdb->get_var("
33
  SELECT SUM(count) AS views
34
- FROM ".$wpdb->prefix."post_views
35
- WHERE id IN (".$post_id.") AND type = 4"
36
  );
37
 
38
- return apply_filters('pvc_get_post_views', $post_views, $post_id);
39
  }
 
40
  }
41
 
42
  /**
43
- * Display post views for a given post
44
  *
45
  * @param int|array $post_id
46
  * @param bool $display
47
  * @return mixed
48
  */
49
- if (!function_exists('pvc_post_views')) {
50
- function pvc_post_views($post_id = 0, $display = true) {
 
51
  // get all data
52
- $post_id = (int)(empty($post_id) ? get_the_ID() : $post_id);
53
- $options = Post_Views_Counter()->get_attribute('options', 'display');
54
- $views = pvc_get_post_views($post_id);
55
 
56
  // prepares display
57
- $label = apply_filters('pvc_post_views_label', (function_exists('icl_t') ? icl_t('Post Views Counter', 'Post Views Label', $options['label']) : $options['label']), $post_id);
58
- $icon_class = ($options['icon_class'] !== '' ? ' '.esc_attr($options['icon_class']) : '');
59
- $icon = apply_filters('pvc_post_views_icon', '<span class="post-views-icon dashicons '.$icon_class.'"></span>', $post_id);
60
 
61
  $html = apply_filters(
62
- 'pvc_post_views_html',
63
- '<div class="post-views post-'.$post_id.' entry-meta">
64
- '.($options['display_style']['icon'] && $icon_class !== '' ? $icon : '').'
65
- '.($options['display_style']['text'] ? '<span class="post-views-label">'.$label.' </span>' : '').'
66
- <span class="post-views-count">'.number_format_i18n($views).'</span>
67
- </div>',
68
- $post_id,
69
- $views,
70
- $label,
71
- $icon
72
  );
73
 
74
- if ($display)
75
  echo $html;
76
  else
77
  return $html;
78
  }
 
79
  }
80
 
81
  /**
82
- * Get most viewed posts
83
  *
84
  * @param array $args
85
  * @return array
86
  */
87
- if(!function_exists('pvc_get_most_viewed_posts')) {
88
- function pvc_get_most_viewed_posts($args = array()) {
 
89
  $args = array_merge(
90
  array(
91
- 'posts_per_page' => 10,
92
- 'order' => 'desc',
93
- 'post_type' => 'post'
94
- ),
95
- $args
96
  );
97
 
98
- $args = apply_filters('pvc_get_most_viewed_posts_args', $args);
99
 
100
  // forces to use filters and post views as order
101
  $args['suppress_filters'] = false;
102
  $args['orderby'] = 'post_views';
103
 
104
- return get_posts($args);
105
  }
 
106
  }
107
 
108
  /**
109
- * Display a list of most viewed posts
110
  *
111
  * @param array $post_id
112
  * @param bool $display
113
  * @return mixed
114
  */
115
- if(!function_exists('pvc_most_viewed_posts')) {
116
- function pvc_most_viewed_posts($args = array(), $display = true) {
 
117
  $defaults = array(
118
- 'number_of_posts' => 5,
119
- 'post_types' => array('post'),
120
- 'order' => 'desc',
121
- 'thumbnail_size' => 'thumbnail',
122
- 'show_post_views' => true,
123
- 'show_post_thumbnail' => false,
124
- 'show_post_excerpt' => false,
125
- 'no_posts_message' => __('No Posts', 'post-views-counter')
126
  );
127
 
128
- $args = apply_filters('pvc_most_viewed_posts_args', wp_parse_args($args, $defaults));
129
 
130
- $args['show_post_views'] = (bool)$args['show_post_views'];
131
- $args['show_post_thumbnail'] = (bool)$args['show_post_thumbnail'];
132
- $args['show_post_excerpt'] = (bool)$args['show_post_excerpt'];
133
 
134
  $posts = pvc_get_most_viewed_posts(
135
  array(
136
- 'posts_per_page' => (isset($args['number_of_posts']) ? (int)$args['number_of_posts'] : $defaults['number_of_posts']),
137
- 'order' => (isset($args['order']) ? $args['order'] : $defaults['order']),
138
- 'post_type' => (isset($args['post_types']) ? $args['post_types'] : $defaults['post_types'])
139
  )
140
  );
141
 
142
- if(!empty($posts)) {
143
  $html = '
144
  <ul>';
145
 
146
- foreach($posts as $post) {
147
- setup_postdata($post);
148
 
149
  $html .= '
150
  <li>';
151
 
152
- if($args['show_post_thumbnail'] && has_post_thumbnail($post->ID)) {
153
  $html .= '
154
  <span class="post-thumbnail">
155
- '.get_the_post_thumbnail($post->ID, $args['thumbnail_size']).'
156
  </span>';
157
  }
158
 
159
  $html .= '
160
- <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>' : '');
161
 
162
  $excerpt = '';
163
 
164
- if($args['show_post_excerpt']) {
165
- if(empty($post->post_excerpt))
166
  $text = $post->post_content;
167
  else
168
  $text = $post->post_excerpt;
169
 
170
- if(!empty($text))
171
- $excerpt = wp_trim_words(str_replace(']]>', ']]&gt;', strip_shortcodes($text)), apply_filters('excerpt_length', 55), apply_filters('excerpt_more', ' '.'[&hellip;]'));
172
  }
173
 
174
- if(!empty($excerpt))
175
  $html .= '
176
- <div class="post-excerpt">'.esc_html($excerpt).'</div>';
177
 
178
  $html .= '
179
  </li>';
@@ -183,16 +185,15 @@ if(!function_exists('pvc_most_viewed_posts')) {
183
 
184
  $html .= '
185
  </ul>';
186
- }
187
- else
188
  $html = $args['no_posts_message'];
189
 
190
- $html = apply_filters('pvc_most_viewed_posts_html', $html, $args);
191
 
192
- if($display)
193
  echo $html;
194
  else
195
  return $html;
196
  }
 
197
  }
198
- ?>
9
  * @since 1.0.0
10
  */
11
 
12
+ if ( ! defined( 'ABSPATH' ) )
13
+ exit;
14
 
15
  /**
16
+ * Get post views for a post or array of posts.
17
  *
18
  * @param int|array $post_id
19
  * @return int
20
  */
21
+ if ( ! function_exists( 'pvc_get_post_views' ) ) {
22
+
23
+ function pvc_get_post_views( $post_id = 0 ) {
24
+ if ( empty( $post_id ) )
25
  $post_id = get_the_ID();
26
 
27
+ if ( is_array( $post_id ) )
28
+ $post_id = implode( ',', array_map( 'intval', $post_id ) );
29
  else
30
+ $post_id = (int) $post_id;
31
 
32
  global $wpdb;
33
 
34
+ $post_views = (int) $wpdb->get_var( "
35
  SELECT SUM(count) AS views
36
+ FROM " . $wpdb->prefix . "post_views
37
+ WHERE id IN (" . $post_id . ") AND type = 4"
38
  );
39
 
40
+ return apply_filters( 'pvc_get_post_views', $post_views, $post_id );
41
  }
42
+
43
  }
44
 
45
  /**
46
+ * Display post views for a given post.
47
  *
48
  * @param int|array $post_id
49
  * @param bool $display
50
  * @return mixed
51
  */
52
+ if ( ! function_exists( 'pvc_post_views' ) ) {
53
+
54
+ function pvc_post_views( $post_id = 0, $display = true ) {
55
  // get all data
56
+ $post_id = (int) (empty( $post_id ) ? get_the_ID() : $post_id);
57
+ $options = Post_Views_Counter()->get_attribute( 'options', 'display' );
58
+ $views = pvc_get_post_views( $post_id );
59
 
60
  // prepares display
61
+ $label = apply_filters( 'pvc_post_views_label', (function_exists( 'icl_t' ) ? icl_t( 'Post Views Counter', 'Post Views Label', $options['label'] ) : $options['label'] ), $post_id );
62
+ $icon_class = ($options['icon_class'] !== '' ? ' ' . esc_attr( $options['icon_class'] ) : '');
63
+ $icon = apply_filters( 'pvc_post_views_icon', '<span class="post-views-icon dashicons ' . $icon_class . '"></span>', $post_id );
64
 
65
  $html = apply_filters(
66
+ 'pvc_post_views_html', '<div class="post-views post-' . $post_id . ' entry-meta">
67
+ ' . ($options['display_style']['icon'] && $icon_class !== '' ? $icon : '') . '
68
+ ' . ($options['display_style']['text'] ? '<span class="post-views-label">' . $label . ' </span>' : '') . '
69
+ <span class="post-views-count">' . number_format_i18n( $views ) . '</span>
70
+ </div>', $post_id, $views, $label, $icon
 
 
 
 
 
71
  );
72
 
73
+ if ( $display )
74
  echo $html;
75
  else
76
  return $html;
77
  }
78
+
79
  }
80
 
81
  /**
82
+ * Get most viewed posts.
83
  *
84
  * @param array $args
85
  * @return array
86
  */
87
+ if ( ! function_exists( 'pvc_get_most_viewed_posts' ) ) {
88
+
89
+ function pvc_get_most_viewed_posts( $args = array() ) {
90
  $args = array_merge(
91
  array(
92
+ 'posts_per_page' => 10,
93
+ 'order' => 'desc',
94
+ 'post_type' => 'post'
95
+ ), $args
 
96
  );
97
 
98
+ $args = apply_filters( 'pvc_get_most_viewed_posts_args', $args );
99
 
100
  // forces to use filters and post views as order
101
  $args['suppress_filters'] = false;
102
  $args['orderby'] = 'post_views';
103
 
104
+ return get_posts( $args );
105
  }
106
+
107
  }
108
 
109
  /**
110
+ * Display a list of most viewed posts.
111
  *
112
  * @param array $post_id
113
  * @param bool $display
114
  * @return mixed
115
  */
116
+ if ( ! function_exists( 'pvc_most_viewed_posts' ) ) {
117
+
118
+ function pvc_most_viewed_posts( $args = array(), $display = true ) {
119
  $defaults = array(
120
+ 'number_of_posts' => 5,
121
+ 'post_types' => array( 'post' ),
122
+ 'order' => 'desc',
123
+ 'thumbnail_size' => 'thumbnail',
124
+ 'show_post_views' => true,
125
+ 'show_post_thumbnail' => false,
126
+ 'show_post_excerpt' => false,
127
+ 'no_posts_message' => __( 'No Posts', 'post-views-counter' )
128
  );
129
 
130
+ $args = apply_filters( 'pvc_most_viewed_posts_args', wp_parse_args( $args, $defaults ) );
131
 
132
+ $args['show_post_views'] = (bool) $args['show_post_views'];
133
+ $args['show_post_thumbnail'] = (bool) $args['show_post_thumbnail'];
134
+ $args['show_post_excerpt'] = (bool) $args['show_post_excerpt'];
135
 
136
  $posts = pvc_get_most_viewed_posts(
137
  array(
138
+ 'posts_per_page' => (isset( $args['number_of_posts'] ) ? (int) $args['number_of_posts'] : $defaults['number_of_posts']),
139
+ 'order' => (isset( $args['order'] ) ? $args['order'] : $defaults['order']),
140
+ 'post_type' => (isset( $args['post_types'] ) ? $args['post_types'] : $defaults['post_types'])
141
  )
142
  );
143
 
144
+ if ( ! empty( $posts ) ) {
145
  $html = '
146
  <ul>';
147
 
148
+ foreach ( $posts as $post ) {
149
+ setup_postdata( $post );
150
 
151
  $html .= '
152
  <li>';
153
 
154
+ if ( $args['show_post_thumbnail'] && has_post_thumbnail( $post->ID ) ) {
155
  $html .= '
156
  <span class="post-thumbnail">
157
+ ' . get_the_post_thumbnail( $post->ID, $args['thumbnail_size'] ) . '
158
  </span>';
159
  }
160
 
161
  $html .= '
162
+ <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>' : '');
163
 
164
  $excerpt = '';
165
 
166
+ if ( $args['show_post_excerpt'] ) {
167
+ if ( empty( $post->post_excerpt ) )
168
  $text = $post->post_content;
169
  else
170
  $text = $post->post_excerpt;
171
 
172
+ if ( ! empty( $text ) )
173
+ $excerpt = wp_trim_words( str_replace( ']]>', ']]&gt;', strip_shortcodes( $text ) ), apply_filters( 'excerpt_length', 55 ), apply_filters( 'excerpt_more', ' ' . '[&hellip;]' ) );
174
  }
175
 
176
+ if ( ! empty( $excerpt ) )
177
  $html .= '
178
+ <div class="post-excerpt">' . esc_html( $excerpt ) . '</div>';
179
 
180
  $html .= '
181
  </li>';
185
 
186
  $html .= '
187
  </ul>';
188
+ } else
 
189
  $html = $args['no_posts_message'];
190
 
191
+ $html = apply_filters( 'pvc_most_viewed_posts_html', $html, $args );
192
 
193
+ if ( $display )
194
  echo $html;
195
  else
196
  return $html;
197
  }
198
+
199
  }
 
includes/query.php CHANGED
@@ -1,5 +1,6 @@
1
  <?php
2
- if(!defined('ABSPATH')) exit;
 
3
 
4
  new Post_Views_Counter_Query();
5
 
@@ -7,65 +8,61 @@ class Post_Views_Counter_Query {
7
 
8
  public function __construct() {
9
  // actions
10
- add_action('pre_get_posts', array(&$this, 'extend_pre_query'), 9);
11
 
12
  // filters
13
- add_filter('posts_join', array(&$this, 'posts_join'), 10, 2);
14
- add_filter('posts_groupby', array(&$this, 'posts_groupby'), 10, 2);
15
- add_filter('posts_orderby', array(&$this, 'posts_orderby'), 10, 2);
16
  }
17
 
18
-
19
  /**
20
- * Extend query with post_views orderby parameter
21
- */
22
- public function extend_pre_query($query) {
23
- if (isset($query->query_vars['orderby']) && $query->query_vars['orderby'] === 'post_views')
24
  $query->order_by_post_views = true;
25
  }
26
 
27
-
28
  /**
29
- * Modify the db query to use post_views parameter
30
- */
31
- public function posts_join($join, $query) {
32
  global $wpdb;
33
 
34
  // is it sorted by post views?
35
- if (isset($query->order_by_post_views) && $query->order_by_post_views)
36
- $join .= " LEFT JOIN ".$wpdb->prefix."post_views pvc ON pvc.id = ".$wpdb->prefix."posts.ID AND pvc.type = 4";
37
 
38
  return $join;
39
  }
40
 
41
-
42
  /**
43
- * Group posts using the post ID
44
- */
45
- public function posts_groupby($groupby, $query) {
46
  global $wpdb;
47
 
48
  // is it sorted by post views?
49
- if (isset($query->order_by_post_views) && $query->order_by_post_views)
50
- $groupby = (trim($groupby) !== '' ? $groupby.', ' : '').$wpdb->prefix.'posts.ID';
51
 
52
  return $groupby;
53
  }
54
 
55
-
56
  /**
57
- * Order posts by post views
58
- */
59
- public function posts_orderby($orderby, $query) {
60
  global $wpdb;
61
 
62
  // is it sorted by post views?
63
- if (isset($query->order_by_post_views) && $query->order_by_post_views) {
64
- $order = $query->get('order');
65
- $orderby = 'pvc.count '.$order.', '.$wpdb->prefix.'posts.ID '.$order;
66
  }
67
 
68
  return $orderby;
69
  }
 
70
  }
71
- ?>
1
  <?php
2
+ if ( ! defined( 'ABSPATH' ) )
3
+ exit;
4
 
5
  new Post_Views_Counter_Query();
6
 
8
 
9
  public function __construct() {
10
  // actions
11
+ add_action( 'pre_get_posts', array( &$this, 'extend_pre_query' ), 9 );
12
 
13
  // filters
14
+ add_filter( 'posts_join', array( &$this, 'posts_join' ), 10, 2 );
15
+ add_filter( 'posts_groupby', array( &$this, 'posts_groupby' ), 10, 2 );
16
+ add_filter( 'posts_orderby', array( &$this, 'posts_orderby' ), 10, 2 );
17
  }
18
 
 
19
  /**
20
+ * Extend query with post_views orderby parameter.
21
+ */
22
+ public function extend_pre_query( $query ) {
23
+ if ( isset( $query->query_vars['orderby'] ) && $query->query_vars['orderby'] === 'post_views' )
24
  $query->order_by_post_views = true;
25
  }
26
 
 
27
  /**
28
+ * Modify the db query to use post_views parameter.
29
+ */
30
+ public function posts_join( $join, $query ) {
31
  global $wpdb;
32
 
33
  // is it sorted by post views?
34
+ if ( isset( $query->order_by_post_views ) && $query->order_by_post_views )
35
+ $join .= " LEFT JOIN " . $wpdb->prefix . "post_views pvc ON pvc.id = " . $wpdb->prefix . "posts.ID AND pvc.type = 4";
36
 
37
  return $join;
38
  }
39
 
 
40
  /**
41
+ * Group posts using the post ID.
42
+ */
43
+ public function posts_groupby( $groupby, $query ) {
44
  global $wpdb;
45
 
46
  // is it sorted by post views?
47
+ if ( isset( $query->order_by_post_views ) && $query->order_by_post_views )
48
+ $groupby = (trim( $groupby ) !== '' ? $groupby . ', ' : '') . $wpdb->prefix . 'posts.ID';
49
 
50
  return $groupby;
51
  }
52
 
 
53
  /**
54
+ * Order posts by post views.
55
+ */
56
+ public function posts_orderby( $orderby, $query ) {
57
  global $wpdb;
58
 
59
  // is it sorted by post views?
60
+ if ( isset( $query->order_by_post_views ) && $query->order_by_post_views ) {
61
+ $order = $query->get( 'order' );
62
+ $orderby = 'pvc.count ' . $order . ', ' . $wpdb->prefix . 'posts.ID ' . $order;
63
  }
64
 
65
  return $orderby;
66
  }
67
+
68
  }
 
includes/settings.php CHANGED
@@ -1,9 +1,11 @@
1
  <?php
2
- if(!defined('ABSPATH')) exit;
 
3
 
4
  new Post_Views_Counter_Settings();
5
 
6
  class Post_Views_Counter_Settings {
 
7
  private $tabs;
8
  private $choices;
9
  private $modes;
@@ -16,71 +18,68 @@ class Post_Views_Counter_Settings {
16
 
17
  public function __construct() {
18
  // set instance
19
- Post_Views_Counter()->add_instance('settings', $this);
20
 
21
  // actions
22
- add_action('admin_init', array(&$this, 'register_settings'));
23
- add_action('admin_menu', array(&$this, 'admin_menu_options'));
24
- add_action('after_setup_theme', array(&$this, 'load_defaults'));
25
- add_action('wp_loaded', array(&$this, 'load_post_types'));
26
-
27
- // filters
28
- add_filter('plugin_row_meta', array(&$this, 'plugin_extend_links'), 10, 2);
29
  }
30
 
31
  /**
32
- * Load default settings
33
- */
34
  public function load_defaults() {
35
  $this->choices = array(
36
- 'yes' => __('Enable', 'post-views-counter'),
37
- 'no' => __('Disable', 'post-views-counter')
38
  );
39
 
40
  $this->modes = array(
41
- 'php' => __('PHP', 'post-views-counter'),
42
- 'js' => __('JavaScript', 'post-views-counter')
43
  );
44
 
45
  $this->time_types = array(
46
- 'minutes' => __('minutes', 'post-views-counter'),
47
- 'hours' => __('hours', 'post-views-counter'),
48
- 'days' => __('days', 'post-views-counter'),
49
- 'weeks' => __('weeks', 'post-views-counter'),
50
- 'months' => __('months', 'post-views-counter'),
51
- 'years' => __('years', 'post-views-counter')
52
  );
53
 
54
  $this->groups = array(
55
- 'robots' => __('robots', 'post-views-counter'),
56
- 'users' => __('logged in users', 'post-views-counter'),
57
- 'guests' => __('guests', 'post-views-counter'),
58
- 'roles' => __('selected user roles', 'post-views-counter')
59
  );
60
 
61
  $this->positions = array(
62
- 'before' => __('before the content', 'post-views-counter'),
63
- 'after' => __('after the content', 'post-views-counter'),
64
- 'manual' => __('manual', 'post-views-counter')
65
  );
66
 
67
  $this->display_styles = array(
68
- 'icon' => __('icon', 'post-views-counter'),
69
- 'text' => __('label', 'post-views-counter')
70
  );
71
 
72
  $this->tabs = array(
73
- 'general' => array(
74
- 'name' => __('General', 'post-views-counter'),
75
- 'key' => 'post_views_counter_settings_general',
76
  'submit' => 'save_pvc_general',
77
- 'reset' => 'reset_pvc_general'
78
  ),
79
- 'display' => array(
80
- 'name' => __('Display', 'post-views-counter'),
81
- 'key' => 'post_views_counter_settings_display',
82
  'submit' => 'save_pvc_display',
83
- 'reset' => 'reset_pvc_display'
84
  )
85
  );
86
 
@@ -88,106 +87,102 @@ class Post_Views_Counter_Settings {
88
  }
89
 
90
  /**
91
- * Get post types avaiable for counting
92
- */
93
  public function load_post_types() {
94
  $post_types = array();
95
 
96
  // built in public post types
97
- foreach (get_post_types(array('_builtin' => true, 'public' => true), 'objects', 'and') as $key => $post_type) {
98
- if($key !== 'attachment')
99
  $post_types[$key] = $post_type->labels->name;
100
  }
101
 
102
  // public custom post types
103
- foreach (get_post_types(array('_builtin' => false, 'public' => true), 'objects', 'and') as $key => $post_type) {
104
  $post_types[$key] = $post_type->labels->name;
105
  }
106
 
107
  // sort post types alphabetically with their keys
108
- asort($post_types, SORT_STRING);
109
 
110
  $this->post_types = $post_types;
111
  }
112
 
113
  /**
114
- * Get all user roles
115
- */
116
  public function get_user_roles() {
117
  global $wp_roles;
118
 
119
  $roles = array();
120
 
121
- foreach (apply_filters('editable_roles', $wp_roles->roles) as $role => $details) {
122
- $roles[$role] = translate_user_role($details['name']);
123
  }
124
 
125
- asort($roles, SORT_STRING);
126
 
127
  return $roles;
128
  }
129
 
130
  /**
131
- * Add options page
132
- */
133
  public function admin_menu_options() {
134
  add_options_page(
135
- __('Post Views Counter', 'post-views-counter'),
136
- __('Post Views Counter', 'post-views-counter'),
137
- 'manage_options',
138
- 'post-views-counter',
139
- array(&$this, 'options_page')
140
  );
141
  }
142
 
143
  /**
144
- * Options page callback
145
- */
146
  public function options_page() {
147
- $tab_key = (isset($_GET['tab']) ? $_GET['tab'] : 'general');
148
 
149
  echo '
150
- <div class="wrap">'.screen_icon().'
151
- <h2>'.__('Post Views Counter', 'post-views-counter').'</h2>
152
  <h2 class="nav-tab-wrapper">';
153
 
154
- foreach ($this->tabs as $key => $name) {
155
  echo '
156
- <a class="nav-tab '.($tab_key == $key ? 'nav-tab-active' : '').'" href="'.esc_url(admin_url('options-general.php?page=post-views-counter&tab='.$key)).'">'.$name['name'].'</a>';
157
  }
158
 
159
  echo '
160
  </h2>
161
  <div class="post-views-counter-settings">
162
  <div class="df-credits">
163
- <h3 class="hndle">'.__('Post Views Counter', 'post-views-counter').' '.Post_Views_Counter()->get_attribute('defaults', 'version').'</h3>
164
  <div class="inside">
165
- <h4 class="inner">'.__('Need support?', 'post-views-counter').'</h4>
166
- <p class="inner">'.__('If you are having problems with this plugin, please talk about them in the', 'post-views-counter').' <a href="http://www.dfactory.eu/support/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=support" target="_blank" title="'.__('Support forum', 'post-views-counter').'">'.__('Support forum', 'post-views-counter').'</a></p>
167
  <hr />
168
- <h4 class="inner">'.__('Do you like this plugin?', 'post-views-counter').'</h4>
169
- <p class="inner"><a href="http://wordpress.org/support/view/plugin-reviews/post-views-counter" target="_blank" title="'.__('Rate it 5', 'post-views-counter').'">'.__('Rate it 5', 'post-views-counter').'</a> '.__('on WordPress.org', 'post-views-counter').'<br />'.
170
- __('Blog about it & link to the', 'post-views-counter').' <a href="http://www.dfactory.eu/plugins/post-views-counter/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=blog-about" target="_blank" title="'.__('plugin page', 'post-views-counter').'">'.__('plugin page', 'post-views-counter').'</a><br/>'.
171
- __('Check out our other', 'post-views-counter').' <a href="http://www.dfactory.eu/plugins/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=other-plugins" target="_blank" title="'.__('WordPress plugins', 'post-views-counter').'">'.__('WordPress plugins', 'post-views-counter').'</a>
172
  </p>
173
  <hr />
174
- <p class="df-link inner">'.__('Created by', 'post-views-counter').' <a href="http://www.dfactory.eu/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=created-by" target="_blank" title="dFactory - Quality plugins for WordPress"><img src="'.POST_VIEWS_COUNTER_URL.'/images/logo-dfactory.png'.'" title="dFactory - Quality plugins for WordPress" alt="dFactory - Quality plugins for WordPress" /></a></p>
175
  </div>
176
  </div>
177
  <form action="options.php" method="post">';
178
 
179
- wp_nonce_field('update-options');
180
- settings_fields($this->tabs[$tab_key]['key']);
181
- do_settings_sections($this->tabs[$tab_key]['key']);
182
 
183
  echo '
184
  <p class="submit">';
185
 
186
- submit_button('', 'primary', $this->tabs[$tab_key]['submit'], false);
187
 
188
  echo ' ';
189
 
190
- submit_button(__('Reset to defaults', 'post-views-counter'), 'secondary reset_pvc_settings', $this->tabs[$tab_key]['reset'], false);
191
 
192
  echo '
193
  </p>
@@ -197,621 +192,586 @@ class Post_Views_Counter_Settings {
197
  </div>';
198
  }
199
 
200
-
201
  /**
202
- * Register settings callback
203
- */
204
- public function register_settings() {
205
  // general options
206
- register_setting('post_views_counter_settings_general', 'post_views_counter_settings_general', array(&$this, 'validate_settings'));
207
- add_settings_section('post_views_counter_settings_general', __('General settings', 'post-views-counter'), '', 'post_views_counter_settings_general');
208
- add_settings_field('pvc_post_types_count', __('Post Types Count', 'post-views-counter'), array(&$this, 'post_types_count'), 'post_views_counter_settings_general', 'post_views_counter_settings_general');
209
- add_settings_field('pvc_counter_mode', __('Counter Mode', 'post-views-counter'), array(&$this, 'counter_mode'), 'post_views_counter_settings_general', 'post_views_counter_settings_general');
210
- add_settings_field('pvc_post_views_column', __('Post Views Column', 'post-views-counter'), array(&$this, 'post_views_column'), 'post_views_counter_settings_general', 'post_views_counter_settings_general');
211
- add_settings_field('pvc_time_between_counts', __('Time Between Counts', 'post-views-counter'), array(&$this, 'time_between_counts'), 'post_views_counter_settings_general', 'post_views_counter_settings_general');
212
- add_settings_field('pvc_reset_counts', __('Reset Data Interval', 'post-views-counter'), array(&$this, 'reset_counts'), 'post_views_counter_settings_general', 'post_views_counter_settings_general');
213
- add_settings_field('pvc_flush_interval', __('Flush Object Cache Interval', 'post-views-counter'), array(&$this, 'flush_interval'), 'post_views_counter_settings_general', 'post_views_counter_settings_general');
214
- add_settings_field('pvc_exclude', __('Exclude Visitors', 'post-views-counter'), array(&$this, 'exclude'), 'post_views_counter_settings_general', 'post_views_counter_settings_general');
215
- add_settings_field('pvc_exclude_ips', __('Exclude IPs', 'post-views-counter'), array(&$this, 'exclude_ips'), 'post_views_counter_settings_general', 'post_views_counter_settings_general');
216
- add_settings_field('pvc_wp_postviews', __('WP-PostViews', 'post-views-counter'), array(&$this, 'wp_postviews'), 'post_views_counter_settings_general', 'post_views_counter_settings_general');
217
- add_settings_field('pvc_deactivation_delete', __('Deactivation', 'post-views-counter'), array(&$this, 'deactivation_delete'), 'post_views_counter_settings_general', 'post_views_counter_settings_general');
218
 
219
  // display options
220
- register_setting('post_views_counter_settings_display', 'post_views_counter_settings_display', array(&$this, 'validate_settings'));
221
- add_settings_section('post_views_counter_settings_display', __('Display settings', 'post-views-counter'), '', 'post_views_counter_settings_display');
222
- add_settings_field('pvc_post_views_label', __('Post Views Label', 'post-views-counter'), array(&$this, 'post_views_label'), 'post_views_counter_settings_display', 'post_views_counter_settings_display');
223
- add_settings_field('pvc_post_types_display', __('Post Types Display', 'post-views-counter'), array(&$this, 'post_types_display'), 'post_views_counter_settings_display', 'post_views_counter_settings_display');
224
- add_settings_field('pvc_restrict_display', __('Restrict Display', 'post-views-counter'), array(&$this, 'restrict_display'), 'post_views_counter_settings_display', 'post_views_counter_settings_display');
225
- add_settings_field('pvc_position', __('Position', 'post-views-counter'), array(&$this, 'position'), 'post_views_counter_settings_display', 'post_views_counter_settings_display');
226
- add_settings_field('pvc_display_style', __('Display Style', 'post-views-counter'), array(&$this, 'display_style'), 'post_views_counter_settings_display', 'post_views_counter_settings_display');
227
- add_settings_field('pvc_icon_class', __('Icon Class', 'post-views-counter'), array(&$this, 'icon_class'), 'post_views_counter_settings_display', 'post_views_counter_settings_display');
228
  }
229
 
230
-
231
  /**
232
- * Post views label option
233
- */
234
  public function post_views_label() {
235
  echo '
236
  <div id="pvc_post_views_label">
237
  <fieldset>
238
- <input type="text" class="large-text" name="post_views_counter_settings_display[label]" value="'.esc_attr(Post_Views_Counter()->get_attribute('options', 'display', 'label')).'" />
239
  <br/>
240
- <span class="description">'.esc_html__('Enter the label for the post views counter field.', 'post-views-counter').'</span>
241
  </fieldset>
242
  </div>';
243
  }
244
 
245
-
246
  /**
247
- * Post types to count option
248
- */
249
  public function post_types_count() {
250
  echo '
251
  <div id="pvc_post_types_count">
252
  <fieldset>
253
- <select class="pvc-chosen" data-placeholder="'.esc_attr__('Select post types', 'post-views-counter').'" name="post_views_counter_settings_general[post_types_count][]" multiple="multiple">';
254
 
255
- foreach ($this->post_types as $post_type => $post_type_name) {
256
  echo '
257
- <option value="'.esc_attr($post_type).'" '.selected(in_array($post_type, Post_Views_Counter()->get_attribute('options', 'general', 'post_types_count'), true), true, false).'>'.esc_html($post_type_name).'</option>';
258
  }
259
 
260
  echo '
261
  </select>
262
  <br/>
263
- <span class="description">'.esc_html__('Select post types for which post views will be counted.', 'post-views-counter').'</span>
264
  </fieldset>
265
  </div>';
266
  }
267
 
268
-
269
  /**
270
- * Post types to display option
271
- */
272
  public function post_types_display() {
273
  echo '
274
  <div id="pvc_post_types_display">
275
  <fieldset>
276
- <select class="pvc-chosen" data-placeholder="'.esc_attr__('Select groups', 'post-views-counter').'" name="post_views_counter_settings_display[post_types_display][]" multiple="multiple">';
277
 
278
- foreach ($this->post_types as $post_type => $post_type_name) {
279
  echo '
280
- <option value="'.esc_attr($post_type).'" '.selected(in_array($post_type, Post_Views_Counter()->get_attribute('options', 'display', 'post_types_display'), true), true, false).'>'.esc_html($post_type_name).'</option>';
281
  }
282
 
283
  echo '
284
  </select>
285
  <br/>
286
- <span class="description">'.esc_html__('Select post types for which post views will be displayed.', 'post-views-counter').'</span>
287
  </fieldset>
288
  </div>';
289
  }
290
 
291
  /**
292
- * Counter mode option
293
- */
294
  public function counter_mode() {
295
  echo '
296
  <div id="pvc_counter_mode">
297
  <fieldset>';
298
 
299
- foreach ($this->modes as $key => $value) {
300
- $key = esc_attr($key);
301
 
302
  echo '
303
- <input id="pvc-counter-mode-'.$key.'" type="radio" name="post_views_counter_settings_general[counter_mode]" value="'.$key.'" '.checked($key, Post_Views_Counter()->get_attribute('options', 'general', 'counter_mode'), false).' /><label for="pvc-counter-mode-'.$key.'">'.esc_html($value).'</label>';
304
  }
305
 
306
  echo '
307
  <br/>
308
- <span class="description">'.esc_html__('Select the method of collecting post views data. If you are using any of the caching plugins select Javascript.', 'post-views-counter').'</span>
309
  </fieldset>
310
  </div>';
311
  }
312
 
313
  /**
314
- * Post views column option
315
- */
316
- public function post_views_column() {
317
  echo '
318
  <div id="pvc_post_views_column">
319
  <fieldset>';
320
 
321
- foreach($this->choices as $key => $value) {
322
- $key = esc_attr($key);
323
 
324
  echo '
325
- <input id="pvc-post-views-column-'.$key.'" type="radio" name="post_views_counter_settings_general[post_views_column]" value="'.$key.'" '.checked($key, (Post_Views_Counter()->get_attribute('options', 'general', 'post_views_column') === true ? 'yes' : 'no'), false).' /><label for="pvc-post-views-column-'.$key.'">'.esc_html($value).'</label>';
326
  }
327
 
328
  echo '
329
  <br/>
330
- <span class="description">'.esc_html__('Enable to display post views count column for each of the selected post types.', 'post-views-counter').'</span>
331
  </fieldset>
332
  </div>';
333
  }
334
 
335
  /**
336
- * Time between counts option
337
- */
338
  public function time_between_counts() {
339
  echo '
340
  <div id="pvc_time_between_counts">
341
  <fieldset>
342
- <input size="4" type="text" name="post_views_counter_settings_general[time_between_counts][number]" value="'.esc_attr(Post_Views_Counter()->get_attribute('options', 'general', 'time_between_counts', 'number')).'" />
343
  <select class="pvc-chosen-short" name="post_views_counter_settings_general[time_between_counts][type]">';
344
 
345
- foreach($this->time_types as $type => $type_name) {
346
  echo '
347
- <option value="'.esc_attr($type).'" '.selected($type, Post_Views_Counter()->get_attribute('options', 'general', 'time_between_counts', 'type'), false).'>'.esc_html($type_name).'</option>';
348
  }
349
 
350
  echo '
351
  </select>
352
  <br/>
353
- <span class="description">'.esc_html__('Enter the time between single user visit count.', 'post-views-counter').'</span>
354
  </fieldset>
355
  </div>';
356
  }
357
 
358
  /**
359
- * Reset counts option
360
- */
361
- public function reset_counts()
362
- {
363
  echo '
364
  <div id="pvc_reset_counts">
365
  <fieldset>
366
- <input size="4" type="text" name="post_views_counter_settings_general[reset_counts][number]" value="'.esc_attr(Post_Views_Counter()->get_attribute('options', 'general', 'reset_counts', 'number')).'" />
367
  <select class="pvc-chosen-short" name="post_views_counter_settings_general[reset_counts][type]">';
368
 
369
- foreach ($this->time_types as $type => $type_name) {
370
  echo '
371
- <option value="'.esc_attr($type).'" '.selected($type, Post_Views_Counter()->get_attribute('options', 'general', 'reset_counts', 'type'), false).'>'.esc_html($type_name).'</option>';
372
  }
373
 
374
  echo '
375
  </select>
376
  <br/>
377
- <span class="description">'.esc_html__('Delete single day post views data older than specified above. Enter 0 (number zero) if you want to preserve your data regardless of its age.', 'post-views-counter').'</span>
378
  </fieldset>
379
  </div>';
380
  }
381
 
382
  /**
383
- * Flush interval option
384
- */
385
  public function flush_interval() {
386
  echo '
387
  <div id="pvc_flush_interval">
388
  <fieldset>
389
- <input size="4" type="text" name="post_views_counter_settings_general[flush_interval][number]" value="'.esc_attr(Post_Views_Counter()->get_attribute('options', 'general', 'flush_interval', 'number')).'" />
390
  <select class="pvc-chosen-short" name="post_views_counter_settings_general[flush_interval][type]">';
391
 
392
- foreach ($this->time_types as $type => $type_name) {
393
  echo '
394
- <option value="'.esc_attr($type).'" '.selected($type, Post_Views_Counter()->get_attribute('options', 'general', 'flush_interval', 'type'), false).'>'.esc_html($type_name).'</option>';
395
  }
396
 
397
  echo '
398
  </select>
399
  <br/>
400
- <span class="description">'.__('How often to flush cached view counts from the object cache into the database. This feature is used only if a persistent object cache is detected and the interval is greater than 0 (number zero)). When used, view counts will be collected and stored in the object cache instead of the database and will then be asynchronously flushed to the database according to the specified interval.<br /><strong>Notice:</strong> Potential data loss may occur if the object cache is cleared/unavailable for the duration of the interval.', 'post-views-counter').'</span>
401
  </fieldset>
402
  </div>';
403
  }
404
 
405
  /**
406
- * Exlude user groups option
407
- */
408
  public function exclude() {
409
  echo '
410
  <div id="pvc_exclude">
411
  <fieldset>
412
- <select class="pvc-chosen" data-placeholder="'.esc_attr__('Select groups', 'post-views-counter').'" name="post_views_counter_settings_general[exclude][groups][]" multiple="multiple">';
413
 
414
- foreach ($this->groups as $type => $type_name) {
415
  echo '
416
- <option value="'.esc_attr($type).'" '.selected(in_array($type, Post_Views_Counter()->get_attribute('options', 'general', 'exclude', 'groups'), true), true, false).'>'.esc_html($type_name).'</option>';
417
  }
418
 
419
  echo '
420
  </select>
421
  <br/>
422
- <div class="pvc_user_roles"'.(in_array('roles', Post_Views_Counter()->get_attribute('options', 'general', 'exclude', 'groups'), true) ? '' : ' style="display: none;"').'>
423
- <select class="pvc-chosen" data-placeholder="'.esc_attr__('Select user roles', 'post-views-counter').'" name="post_views_counter_settings_general[exclude][roles][]" multiple="multiple">';
424
 
425
- foreach ($this->user_roles as $role => $role_name) {
426
  echo '
427
- <option value="'.esc_attr($role).'" '.selected(in_array($role, Post_Views_Counter()->get_attribute('options', 'general', 'exclude', 'roles'), true), true, false).'>'.esc_html($role_name).'</option>';
428
  }
429
 
430
  echo '
431
  </select>
432
  <br/>
433
  </div>
434
- <span class="description">'.esc_html__('Select the type of visitors to be excluded from post views count.', 'post-views-counter').'</span>
435
  </fieldset>
436
  </div>';
437
  }
438
 
439
  /**
440
- * Exclude IPs option
441
- */
442
  public function exclude_ips() {
443
  echo '
444
  <div id="pvc_exclude_ips">
445
  <fieldset>';
446
 
447
- foreach (Post_Views_Counter()->get_attribute('options', 'general', 'exclude_ips') as $key => $ip) {
448
  echo '
449
  <div class="ip-box">
450
- <input type="text" name="post_views_counter_settings_general[exclude_ips][]" value="'.esc_attr($ip).'" /> <input type="button" class="button button-secondary remove-exclude-ip" value="'.esc_attr__('Remove', 'post-views-counter').'" />
451
  </div>';
452
  }
453
 
454
  // lovely php 5.2 limitations
455
- $ips = Post_Views_Counter()->get_attribute('options', 'general', 'exclude_ips');
456
 
457
  echo '
458
  <div class="ip-box">
459
- <input type="text" name="post_views_counter_settings_general[exclude_ips][]" value="" /> <input type="button" class="button button-secondary remove-exclude-ip" value="'.esc_attr__('Remove', 'post-views-counter').'"'.(empty($ips) ? ' style="display: none;"' : '').' /> <input type="button" class="button button-secondary add-exclude-ip" value="'.esc_attr__('Add new', 'post-views-counter').'" /> <input type="button" class="button button-secondary add-current-ip" value="'.esc_attr__('Add my current IP', 'post-views-counter').'" data-rel="'.esc_attr($_SERVER['REMOTE_ADDR']).'" />
460
  </div>
461
- <span class="description">'.esc_html__('Enter the IP addresses to be excluded from post views count.', 'post-views-counter').'</span>
462
  </fieldset>
463
  </div>';
464
  }
465
 
466
  /**
467
- * WP-PostViews import option
468
- */
469
  public function wp_postviews() {
470
  echo '
471
  <div id="pvc_wp_postviews">
472
  <fieldset>
473
- <input type="submit" class="button button-secondary" name="post_views_counter_import_wp_postviews" value="'.__('Import', 'post-views-counter').'"/>
474
  <br/>
475
- <p class="description">'.esc_html__('Import post views data from WP-PostViews plugin.', 'post-views-counter').'</p>
476
- <input id="pvc-wp-postviews" type="checkbox" name="post_views_counter_import_wp_postviews_override"/><label for="pvc-wp-postviews">'.esc_html__('Override existing Post Views Counter data.', 'post-views-counter').'</label>
477
  </fieldset>
478
  </div>';
479
  }
480
 
481
  /**
482
- * Plugin deactivation option
483
- */
484
  public function deactivation_delete() {
485
  echo '
486
  <div id="pvc_deactivation_delete">
487
  <fieldset>';
488
 
489
- foreach ($this->choices as $key => $value) {
490
- $key = esc_attr($key);
491
 
492
  echo '
493
- <input id="pvc-deactivation-delete-'.$key.'" type="radio" name="post_views_counter_settings_general[deactivation_delete]" value="'.$key.'" '.checked($key, (Post_Views_Counter()->get_attribute('options', 'general', 'deactivation_delete') === true ? 'yes' : 'no'), false).' /><label for="pvc-deactivation-delete-'.$key.'">'.esc_html($value).'</label>';
494
  }
495
 
496
  echo '
497
  <br/>
498
- <span class="description">'.esc_html__('Enable to delete all plugin data on deactivation.', 'post-views-counter').'</span>
499
  </fieldset>
500
  </div>';
501
  }
502
 
503
  /**
504
- * Counter position option
505
- */
506
  public function position() {
507
  echo '
508
  <div id="pvc_position">
509
  <fieldset>
510
  <select class="pvc-chosen-short" name="post_views_counter_settings_display[position]">';
511
 
512
- foreach ($this->positions as $position => $position_name) {
513
  echo '
514
- <option value="'.esc_attr($position).'" '.selected($position, Post_Views_Counter()->get_attribute('options', 'display', 'position'), false).'>'.esc_html($position_name).'</option>';
515
  }
516
 
517
  echo '
518
  </select>
519
  <br/>
520
- <span class="description">'.esc_html__('Select where would you like to display the post views counter. Use [post-views] shortcode for manual display.', 'post-views-counter').'</span>
521
  </fieldset>
522
  </div>';
523
  }
524
 
525
  /**
526
- * Counter style option
527
- */
528
- public function display_style() {
529
  echo '
530
  <div id="pvc_display_style">
531
  <fieldset>';
532
 
533
- foreach ($this->display_styles as $display => $style) {
534
- $display = esc_attr($display);
535
 
536
  echo '
537
- <input id="pvc-display-style-'.$display.'" type="checkbox" name="post_views_counter_settings_display[display_style]['.$display.']" value="'.$display.'" '.checked(true, Post_Views_Counter()->get_attribute('options', 'display', 'display_style', $display), false).' /><label for="pvc-display-style-'.$display.'">'.esc_html($style).'</label>';
538
  }
539
 
540
  echo '
541
  <br/>
542
- <span class="description">'.esc_html__('Choose how to display the post views counter.', 'post-views-counter').'</span>
543
  </fieldset>
544
  </div>';
545
  }
546
 
547
  /**
548
- * Counter icon class option
549
- */
550
  public function icon_class() {
551
  echo '
552
  <div id="pvc_icon_class">
553
  <fieldset>
554
- <input type="text" name="post_views_counter_settings_display[icon_class]" class="large-text" value="'.esc_attr(Post_Views_Counter()->get_attribute('options', 'display', 'icon_class')).'"/>
555
  <br/>
556
- <span class="description">'.sprintf(__('Enter the post views icon class. Any of the <a href="%s" target="_blank">Dashicons</a> classes are available.', 'post-views-counter'), 'http://melchoyce.github.io/dashicons/').'</span>
557
  </fieldset>
558
  </div>';
559
  }
560
 
561
-
562
  /**
563
- * Restrict display option
564
- */
565
  public function restrict_display() {
566
  echo '
567
  <div id="pvc_restrict_display">
568
  <fieldset>
569
- <select class="pvc-chosen" data-placeholder="'.esc_attr__('Select groups', 'post-views-counter').'" name="post_views_counter_settings_display[restrict_display][groups][]" multiple="multiple">';
 
 
570
 
571
- foreach ($this->groups as $type => $type_name) {
572
-
573
- if ($type === 'robots')
574
  continue;
575
 
576
  echo '
577
- <option value="'.esc_attr($type).'" '.selected(in_array($type, Post_Views_Counter()->get_attribute('options', 'display', 'restrict_display', 'groups'), true), true, false).'>'.esc_html($type_name).'</option>';
578
  }
579
 
580
  echo '
581
  </select>
582
  <br/>
583
- <div class="pvc_user_roles"'.(in_array('roles', Post_Views_Counter()->get_attribute('options', 'display', 'restrict_display', 'groups'), true) ? '' : ' style="display: none;"').'>
584
- <select class="pvc-chosen" data-placeholder="'.esc_attr__('Select user roles', 'post-views-counter').'" name="post_views_counter_settings_display[restrict_display][roles][]" multiple="multiple">';
585
 
586
- foreach ($this->user_roles as $role => $role_name) {
587
  echo '
588
- <option value="'.esc_attr($role).'" '.selected(in_array($role, Post_Views_Counter()->get_attribute('options', 'display', 'restrict_display', 'roles'), true), true, false).'>'.esc_html($role_name).'</option>';
589
  }
590
 
591
  echo '
592
  </select>
593
  <br/>
594
  </div>
595
- <span class="description">'.esc_html__('Use it to hide the post views counter from selected type of visitors.', 'post-views-counter').'</span>
596
  </fieldset>
597
  </div>';
598
  }
599
 
600
-
601
  /**
602
- * Validate general settings
603
- */
604
- public function validate_settings($input) {
605
- if (isset($_POST['post_views_counter_import_wp_postviews'])) {
606
  global $wpdb;
607
 
608
  $views = $wpdb->get_results(
609
- "SELECT post_id, meta_value FROM ".$wpdb->postmeta." WHERE meta_key = 'views'",
610
- ARRAY_A,
611
- 0
612
  );
613
 
614
- if (!empty($views)) {
615
- $input = Post_Views_Counter()->get_attribute('defaults', 'general');
616
  $input['wp_postviews_import'] = true;
617
 
618
  $sql = '';
619
 
620
- foreach($views as $view) {
621
- $sql[] = "(".$view['post_id'].", 4, 'total', ".$view['meta_value'].")";
622
  }
623
 
624
- $wpdb->query("INSERT INTO ".$wpdb->prefix."post_views(id, type, period, count) VALUES ".implode(',', $sql)." ON DUPLICATE KEY UPDATE count = ".(isset($_POST['post_views_counter_import_wp_postviews_override']) ? '' : 'count + ')."VALUES(count)");
625
 
626
- add_settings_error('wp_postviews_import', 'wp_postviews_import', __('WP-PostViews data imported succesfully.', 'post-views-counter'), 'updated');
627
  } else {
628
- add_settings_error('wp_postviews_import', 'wp_postviews_import', __('There was no data to import.', 'post-views-counter'), 'updated');
629
  }
630
- }
631
- elseif (isset($_POST['save_pvc_general'])) {
632
  // post types count
633
- if (isset($input['post_types_count'])) {
634
  $post_types = array();
635
 
636
- foreach ($input['post_types_count'] as $post_type) {
637
- if (isset($this->post_types[$post_type]))
638
  $post_types[] = $post_type;
639
  }
640
 
641
- $input['post_types_count'] = array_unique($post_types);
642
- }
643
- else
644
  $input['post_types_count'] = array();
645
 
646
  // counter mode
647
- $input['counter_mode'] = (isset($input['counter_mode'], $this->modes[$input['counter_mode']]) ? $input['counter_mode'] : Post_Views_Counter()->get_attribute('defaults', 'general', 'counter_mode'));
648
 
649
  // post views column
650
- $input['post_views_column'] = (isset($input['post_views_column'], $this->choices[$input['post_views_column']]) ? ($input['post_views_column'] === 'yes' ? true : false) : Post_Views_Counter()->get_attribute('defaults', 'general', 'post_views_column'));
651
 
652
  // time between counts
653
- $input['time_between_counts']['number'] = (int)(isset($input['time_between_counts']['number']) ? $input['time_between_counts']['number'] : Post_Views_Counter()->get_attribute('defaults', 'general', 'time_between_counts', 'number'));
654
- $input['time_between_counts']['type'] = (isset($input['time_between_counts']['type'], $this->time_types[$input['time_between_counts']['type']]) ? $input['time_between_counts']['type'] : Post_Views_Counter()->get_attribute('defaults', 'general', 'time_between_counts', 'type'));
655
 
656
  // flush interval
657
- $input['flush_interval']['number'] = (int)(isset($input['flush_interval']['number']) ? $input['flush_interval']['number'] : Post_Views_Counter()->get_attribute('defaults', 'general', 'flush_interval', 'number'));
658
- $input['flush_interval']['type'] = (isset($input['flush_interval']['type'], $this->time_types[$input['flush_interval']['type']]) ? $input['flush_interval']['type'] : Post_Views_Counter()->get_attribute('defaults', 'general', 'flush_interval', 'type'));
659
-
660
  // Since the settings are about to be saved and cache flush interval could've changed,
661
  // we want to make sure that any changes done on the settings page are in effect immediately
662
  // (instead of having to wait for the previous schedule to occur).
663
  // We achieve that by making sure to clear any previous cache flush schedules and
664
  // schedule the new one if the specified interval is > 0
665
  Post_Views_Counter()->remove_cache_flush();
666
-
667
  if ( $input['flush_interval']['number'] > 0 ) {
668
  Post_Views_Counter()->schedule_cache_flush();
669
  }
670
 
671
  // reset counts
672
- $input['reset_counts']['number'] = (int)(isset($input['reset_counts']['number']) ? $input['reset_counts']['number'] : Post_Views_Counter()->get_attribute('defaults', 'general', 'reset_counts', 'number'));
673
- $input['reset_counts']['type'] = (isset($input['reset_counts']['type'], $this->time_types[$input['reset_counts']['type']]) ? $input['reset_counts']['type'] : Post_Views_Counter()->get_attribute('defaults', 'general', 'reset_counts', 'type'));
674
 
675
  // run cron on next visit?
676
  $input['cron_run'] = ($input['reset_counts']['number'] > 0 ? true : false);
677
- $input['cron_update'] = ($input['cron_run'] && (Post_Views_Counter()->get_attribute('options', 'general', 'reset_counts', 'number') !== $input['reset_counts']['number'] || Post_Views_Counter()->get_attribute('options', 'general', 'reset_counts', 'type') !== $input['reset_counts']['type']) ? true : false);
678
 
679
  // exclude
680
- if (isset($input['exclude']['groups'])) {
681
  $groups = array();
682
 
683
- foreach ($input['exclude']['groups'] as $group) {
684
- if (isset($this->groups[$group]))
685
  $groups[] = $group;
686
  }
687
 
688
- $input['exclude']['groups'] = array_unique($groups);
689
  } else
690
  $input['exclude']['groups'] = array();
691
 
692
- if (in_array('roles', $input['exclude']['groups'], true) && isset($input['exclude']['roles'])) {
693
  $roles = array();
694
 
695
- foreach ($input['exclude']['roles'] as $role)
696
- {
697
- if (isset($this->user_roles[$role]))
698
  $roles[] = $role;
699
  }
700
 
701
- $input['exclude']['roles'] = array_unique($roles);
702
  } else
703
  $input['exclude']['roles'] = array();
704
 
705
  // exclude ips
706
- if(isset($input['exclude_ips'])) {
707
-
708
  $ips = array();
709
 
710
- foreach($input['exclude_ips'] as $ip) {
711
- if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
712
  $ips[] = $ip;
713
  }
714
 
715
- $input['exclude_ips'] = array_unique($ips);
716
  }
717
 
718
  // deactivation delete
719
- $input['deactivation_delete'] = (isset($input['deactivation_delete'], $this->choices[$input['deactivation_delete']]) ? ($input['deactivation_delete'] === 'yes' ? true : false) : Post_Views_Counter()->get_attribute('defaults', 'general', 'deactivation_delete'));
720
-
721
- } elseif (isset($_POST['save_pvc_display'])) {
722
-
723
  // post views label
724
- $input['label'] = (isset($input['label']) ? $input['label'] : Post_Views_Counter()->get_attribute('defaults', 'general', 'label'));
725
 
726
- if (function_exists('icl_register_string'))
727
- icl_register_string('Post Views Counter', 'Post Views Label', $input['label']);
728
 
729
  // position
730
- $input['position'] = (isset($input['position'], $this->positions[$input['position']]) ? $input['position'] : Post_Views_Counter()->get_attribute('defaults', 'general', 'position'));
731
 
732
  // display style
733
- $input['display_style']['icon'] = (isset($input['display_style']['icon']) ? true : false);
734
- $input['display_style']['text'] = (isset($input['display_style']['text']) ? true : false);
735
 
736
  // link to post
737
- $input['link_to_post'] = (isset($input['link_to_post'], $this->choices[$input['link_to_post']]) ? ($input['link_to_post'] === 'yes' ? true : false) : Post_Views_Counter()->get_attribute('defaults', 'general', 'link_to_post'));
738
 
739
  // icon class
740
- $input['icon_class'] = (isset($input['icon_class']) ? trim($input['icon_class']) : Post_Views_Counter()->get_attribute('defaults', 'general', 'icon_class'));
741
 
742
  // post types display
743
- if (isset($input['post_types_display'])) {
744
  $post_types = array();
745
 
746
- foreach($input['post_types_display'] as $post_type)
747
- {
748
- if(isset($this->post_types[$post_type]))
749
  $post_types[] = $post_type;
750
  }
751
 
752
- $input['post_types_display'] = array_unique($post_types);
753
  } else
754
  $input['post_types_display'] = array();
755
 
756
  // restrict display
757
- if (isset($input['restrict_display']['groups'])) {
758
  $groups = array();
759
 
760
- foreach ($input['restrict_display']['groups'] as $group) {
761
- if ($group === 'robots')
762
  continue;
763
 
764
- if (isset($this->groups[$group]))
765
  $groups[] = $group;
766
  }
767
 
768
- $input['restrict_display']['groups'] = array_unique($groups);
769
  } else
770
  $input['restrict_display']['groups'] = array();
771
 
772
- if (in_array('roles', $input['restrict_display']['groups'], true) && isset($input['restrict_display']['roles'])) {
773
  $roles = array();
774
 
775
- foreach ($input['restrict_display']['roles'] as $role) {
776
- if (isset($this->user_roles[$role]))
777
  $roles[] = $role;
778
  }
779
 
780
- $input['restrict_display']['roles'] = array_unique($roles);
781
  } else
782
  $input['restrict_display']['roles'] = array();
783
- } elseif (isset($_POST['reset_pvc_general'])) {
784
- $input = Post_Views_Counter()->get_attribute('defaults', 'general');
785
 
786
- add_settings_error('reset_general_settings', 'settings_reset', __('General settings restored to defaults.', 'post-views-counter'), 'updated');
787
- } elseif (isset($_POST['reset_pvc_display'])) {
788
- $input = Post_Views_Counter()->get_attribute('defaults', 'display');
789
 
790
- add_settings_error('reset_general_settings', 'settings_reset', __('Display settings restored to defaults.', 'post-views-counter'), 'updated');
791
  }
792
 
793
  return $input;
794
  }
795
 
796
-
797
- /**
798
- * Add links to plugin support forum
799
- */
800
- public function plugin_extend_links($links, $file) {
801
-
802
- if (!current_user_can('install_plugins'))
803
- return $links;
804
-
805
- $plugin = plugin_basename(__FILE__);
806
-
807
- if ($file == $plugin) {
808
- return array_merge(
809
- $links,
810
- array(sprintf('<a href="http://www.dfactory.eu/support/forum/post-views-counter/" target="_blank">%s</a>', __('Support', 'post-views-counter')))
811
- );
812
- }
813
-
814
- return $links;
815
- }
816
  }
817
- ?>
1
  <?php
2
+ if ( ! defined( 'ABSPATH' ) )
3
+ exit;
4
 
5
  new Post_Views_Counter_Settings();
6
 
7
  class Post_Views_Counter_Settings {
8
+
9
  private $tabs;
10
  private $choices;
11
  private $modes;
18
 
19
  public function __construct() {
20
  // set instance
21
+ Post_Views_Counter()->add_instance( 'settings', $this );
22
 
23
  // actions
24
+ add_action( 'admin_init', array( &$this, 'register_settings' ) );
25
+ add_action( 'admin_menu', array( &$this, 'admin_menu_options' ) );
26
+ add_action( 'after_setup_theme', array( &$this, 'load_defaults' ) );
27
+ add_action( 'wp_loaded', array( &$this, 'load_post_types' ) );
 
 
 
28
  }
29
 
30
  /**
31
+ * Load default settings.
32
+ */
33
  public function load_defaults() {
34
  $this->choices = array(
35
+ 'yes' => __( 'Enable', 'post-views-counter' ),
36
+ 'no' => __( 'Disable', 'post-views-counter' )
37
  );
38
 
39
  $this->modes = array(
40
+ 'php' => __( 'PHP', 'post-views-counter' ),
41
+ 'js' => __( 'JavaScript', 'post-views-counter' )
42
  );
43
 
44
  $this->time_types = array(
45
+ 'minutes' => __( 'minutes', 'post-views-counter' ),
46
+ 'hours' => __( 'hours', 'post-views-counter' ),
47
+ 'days' => __( 'days', 'post-views-counter' ),
48
+ 'weeks' => __( 'weeks', 'post-views-counter' ),
49
+ 'months' => __( 'months', 'post-views-counter' ),
50
+ 'years' => __( 'years', 'post-views-counter' )
51
  );
52
 
53
  $this->groups = array(
54
+ 'robots' => __( 'robots', 'post-views-counter' ),
55
+ 'users' => __( 'logged in users', 'post-views-counter' ),
56
+ 'guests' => __( 'guests', 'post-views-counter' ),
57
+ 'roles' => __( 'selected user roles', 'post-views-counter' )
58
  );
59
 
60
  $this->positions = array(
61
+ 'before' => __( 'before the content', 'post-views-counter' ),
62
+ 'after' => __( 'after the content', 'post-views-counter' ),
63
+ 'manual' => __( 'manual', 'post-views-counter' )
64
  );
65
 
66
  $this->display_styles = array(
67
+ 'icon' => __( 'icon', 'post-views-counter' ),
68
+ 'text' => __( 'label', 'post-views-counter' )
69
  );
70
 
71
  $this->tabs = array(
72
+ 'general' => array(
73
+ 'name' => __( 'General', 'post-views-counter' ),
74
+ 'key' => 'post_views_counter_settings_general',
75
  'submit' => 'save_pvc_general',
76
+ 'reset' => 'reset_pvc_general'
77
  ),
78
+ 'display' => array(
79
+ 'name' => __( 'Display', 'post-views-counter' ),
80
+ 'key' => 'post_views_counter_settings_display',
81
  'submit' => 'save_pvc_display',
82
+ 'reset' => 'reset_pvc_display'
83
  )
84
  );
85
 
87
  }
88
 
89
  /**
90
+ * Get post types avaiable for counting.
91
+ */
92
  public function load_post_types() {
93
  $post_types = array();
94
 
95
  // built in public post types
96
+ foreach ( get_post_types( array( '_builtin' => true, 'public' => true ), 'objects', 'and' ) as $key => $post_type ) {
97
+ if ( $key !== 'attachment' )
98
  $post_types[$key] = $post_type->labels->name;
99
  }
100
 
101
  // public custom post types
102
+ foreach ( get_post_types( array( '_builtin' => false, 'public' => true ), 'objects', 'and' ) as $key => $post_type ) {
103
  $post_types[$key] = $post_type->labels->name;
104
  }
105
 
106
  // sort post types alphabetically with their keys
107
+ asort( $post_types, SORT_STRING );
108
 
109
  $this->post_types = $post_types;
110
  }
111
 
112
  /**
113
+ * Get all user roles.
114
+ */
115
  public function get_user_roles() {
116
  global $wp_roles;
117
 
118
  $roles = array();
119
 
120
+ foreach ( apply_filters( 'editable_roles', $wp_roles->roles ) as $role => $details ) {
121
+ $roles[$role] = translate_user_role( $details['name'] );
122
  }
123
 
124
+ asort( $roles, SORT_STRING );
125
 
126
  return $roles;
127
  }
128
 
129
  /**
130
+ * Add options page.
131
+ */
132
  public function admin_menu_options() {
133
  add_options_page(
134
+ __( 'Post Views Counter', 'post-views-counter' ), __( 'Post Views Counter', 'post-views-counter' ), 'manage_options', 'post-views-counter', array( &$this, 'options_page' )
 
 
 
 
135
  );
136
  }
137
 
138
  /**
139
+ * Options page callback.
140
+ */
141
  public function options_page() {
142
+ $tab_key = (isset( $_GET['tab'] ) ? $_GET['tab'] : 'general');
143
 
144
  echo '
145
+ <div class="wrap">' . screen_icon() . '
146
+ <h2>' . __( 'Post Views Counter', 'post-views-counter' ) . '</h2>
147
  <h2 class="nav-tab-wrapper">';
148
 
149
+ foreach ( $this->tabs as $key => $name ) {
150
  echo '
151
+ <a class="nav-tab ' . ($tab_key == $key ? 'nav-tab-active' : '') . '" href="' . esc_url( admin_url( 'options-general.php?page=post-views-counter&tab=' . $key ) ) . '">' . $name['name'] . '</a>';
152
  }
153
 
154
  echo '
155
  </h2>
156
  <div class="post-views-counter-settings">
157
  <div class="df-credits">
158
+ <h3 class="hndle">' . __( 'Post Views Counter', 'post-views-counter' ) . ' ' . Post_Views_Counter()->get_attribute( 'defaults', 'version' ) . '</h3>
159
  <div class="inside">
160
+ <h4 class="inner">' . __( 'Need support?', 'post-views-counter' ) . '</h4>
161
+ <p class="inner">' . __( 'If you are having problems with this plugin, please talk about them in the', 'post-views-counter' ) . ' <a href="http://www.dfactory.eu/support/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=support" target="_blank" title="' . __( 'Support forum', 'post-views-counter' ) . '">' . __( 'Support forum', 'post-views-counter' ) . '</a></p>
162
  <hr />
163
+ <h4 class="inner">' . __( 'Do you like this plugin?', 'post-views-counter' ) . '</h4>
164
+ <p class="inner"><a href="http://wordpress.org/support/view/plugin-reviews/post-views-counter" target="_blank" title="' . __( 'Rate it 5', 'post-views-counter' ) . '">' . __( 'Rate it 5', 'post-views-counter' ) . '</a> ' . __( 'on WordPress.org', 'post-views-counter' ) . '<br />' .
165
+ __( 'Blog about it & link to the', 'post-views-counter' ) . ' <a href="http://www.dfactory.eu/plugins/post-views-counter/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=blog-about" target="_blank" title="' . __( 'plugin page', 'post-views-counter' ) . '">' . __( 'plugin page', 'post-views-counter' ) . '</a><br/>' .
166
+ __( 'Check out our other', 'post-views-counter' ) . ' <a href="http://www.dfactory.eu/plugins/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=other-plugins" target="_blank" title="' . __( 'WordPress plugins', 'post-views-counter' ) . '">' . __( 'WordPress plugins', 'post-views-counter' ) . '</a>
167
  </p>
168
  <hr />
169
+ <p class="df-link inner">' . __( 'Created by', 'post-views-counter' ) . ' <a href="http://www.dfactory.eu/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=created-by" target="_blank" title="dFactory - Quality plugins for WordPress"><img src="' . POST_VIEWS_COUNTER_URL . '/images/logo-dfactory.png' . '" title="dFactory - Quality plugins for WordPress" alt="dFactory - Quality plugins for WordPress" /></a></p>
170
  </div>
171
  </div>
172
  <form action="options.php" method="post">';
173
 
174
+ wp_nonce_field( 'update-options' );
175
+ settings_fields( $this->tabs[$tab_key]['key'] );
176
+ do_settings_sections( $this->tabs[$tab_key]['key'] );
177
 
178
  echo '
179
  <p class="submit">';
180
 
181
+ submit_button( '', 'primary', $this->tabs[$tab_key]['submit'], false );
182
 
183
  echo ' ';
184
 
185
+ submit_button( __( 'Reset to defaults', 'post-views-counter' ), 'secondary reset_pvc_settings', $this->tabs[$tab_key]['reset'], false );
186
 
187
  echo '
188
  </p>
192
  </div>';
193
  }
194
 
 
195
  /**
196
+ * Register settings callback.
197
+ */
198
+ public function register_settings() {
199
  // general options
200
+ register_setting( 'post_views_counter_settings_general', 'post_views_counter_settings_general', array( &$this, 'validate_settings' ) );
201
+ add_settings_section( 'post_views_counter_settings_general', __( 'General settings', 'post-views-counter' ), '', 'post_views_counter_settings_general' );
202
+ add_settings_field( 'pvc_post_types_count', __( 'Post Types Count', 'post-views-counter' ), array( &$this, 'post_types_count' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
203
+ add_settings_field( 'pvc_counter_mode', __( 'Counter Mode', 'post-views-counter' ), array( &$this, 'counter_mode' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
204
+ add_settings_field( 'pvc_post_views_column', __( 'Post Views Column', 'post-views-counter' ), array( &$this, 'post_views_column' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
205
+ add_settings_field( 'pvc_time_between_counts', __( 'Time Between Counts', 'post-views-counter' ), array( &$this, 'time_between_counts' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
206
+ add_settings_field( 'pvc_reset_counts', __( 'Reset Data Interval', 'post-views-counter' ), array( &$this, 'reset_counts' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
207
+ add_settings_field( 'pvc_flush_interval', __( 'Flush Object Cache Interval', 'post-views-counter' ), array( &$this, 'flush_interval' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
208
+ add_settings_field( 'pvc_exclude', __( 'Exclude Visitors', 'post-views-counter' ), array( &$this, 'exclude' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
209
+ add_settings_field( 'pvc_exclude_ips', __( 'Exclude IPs', 'post-views-counter' ), array( &$this, 'exclude_ips' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
210
+ add_settings_field( 'pvc_wp_postviews', __( 'WP-PostViews', 'post-views-counter' ), array( &$this, 'wp_postviews' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
211
+ add_settings_field( 'pvc_deactivation_delete', __( 'Deactivation', 'post-views-counter' ), array( &$this, 'deactivation_delete' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
212
 
213
  // display options
214
+ register_setting( 'post_views_counter_settings_display', 'post_views_counter_settings_display', array( &$this, 'validate_settings' ) );
215
+ add_settings_section( 'post_views_counter_settings_display', __( 'Display settings', 'post-views-counter' ), '', 'post_views_counter_settings_display' );
216
+ add_settings_field( 'pvc_post_views_label', __( 'Post Views Label', 'post-views-counter' ), array( &$this, 'post_views_label' ), 'post_views_counter_settings_display', 'post_views_counter_settings_display' );
217
+ add_settings_field( 'pvc_post_types_display', __( 'Post Types Display', 'post-views-counter' ), array( &$this, 'post_types_display' ), 'post_views_counter_settings_display', 'post_views_counter_settings_display' );
218
+ add_settings_field( 'pvc_restrict_display', __( 'Restrict Display', 'post-views-counter' ), array( &$this, 'restrict_display' ), 'post_views_counter_settings_display', 'post_views_counter_settings_display' );
219
+ add_settings_field( 'pvc_position', __( 'Position', 'post-views-counter' ), array( &$this, 'position' ), 'post_views_counter_settings_display', 'post_views_counter_settings_display' );
220
+ add_settings_field( 'pvc_display_style', __( 'Display Style', 'post-views-counter' ), array( &$this, 'display_style' ), 'post_views_counter_settings_display', 'post_views_counter_settings_display' );
221
+ add_settings_field( 'pvc_icon_class', __( 'Icon Class', 'post-views-counter' ), array( &$this, 'icon_class' ), 'post_views_counter_settings_display', 'post_views_counter_settings_display' );
222
  }
223
 
 
224
  /**
225
+ * Post views label option.
226
+ */
227
  public function post_views_label() {
228
  echo '
229
  <div id="pvc_post_views_label">
230
  <fieldset>
231
+ <input type="text" class="large-text" name="post_views_counter_settings_display[label]" value="' . esc_attr( Post_Views_Counter()->get_attribute( 'options', 'display', 'label' ) ) . '" />
232
  <br/>
233
+ <span class="description">' . esc_html__( 'Enter the label for the post views counter field.', 'post-views-counter' ) . '</span>
234
  </fieldset>
235
  </div>';
236
  }
237
 
 
238
  /**
239
+ * Post types to count option.
240
+ */
241
  public function post_types_count() {
242
  echo '
243
  <div id="pvc_post_types_count">
244
  <fieldset>
245
+ <select class="pvc-chosen" data-placeholder="' . esc_attr__( 'Select post types', 'post-views-counter' ) . '" name="post_views_counter_settings_general[post_types_count][]" multiple="multiple">';
246
 
247
+ foreach ( $this->post_types as $post_type => $post_type_name ) {
248
  echo '
249
+ <option value="' . esc_attr( $post_type ) . '" ' . selected( in_array( $post_type, Post_Views_Counter()->get_attribute( 'options', 'general', 'post_types_count' ), true ), true, false ) . '>' . esc_html( $post_type_name ) . '</option>';
250
  }
251
 
252
  echo '
253
  </select>
254
  <br/>
255
+ <span class="description">' . esc_html__( 'Select post types for which post views will be counted.', 'post-views-counter' ) . '</span>
256
  </fieldset>
257
  </div>';
258
  }
259
 
 
260
  /**
261
+ * Post types to display option.
262
+ */
263
  public function post_types_display() {
264
  echo '
265
  <div id="pvc_post_types_display">
266
  <fieldset>
267
+ <select class="pvc-chosen" data-placeholder="' . esc_attr__( 'Select groups', 'post-views-counter' ) . '" name="post_views_counter_settings_display[post_types_display][]" multiple="multiple">';
268
 
269
+ foreach ( $this->post_types as $post_type => $post_type_name ) {
270
  echo '
271
+ <option value="' . esc_attr( $post_type ) . '" ' . selected( in_array( $post_type, Post_Views_Counter()->get_attribute( 'options', 'display', 'post_types_display' ), true ), true, false ) . '>' . esc_html( $post_type_name ) . '</option>';
272
  }
273
 
274
  echo '
275
  </select>
276
  <br/>
277
+ <span class="description">' . esc_html__( 'Select post types for which post views will be displayed.', 'post-views-counter' ) . '</span>
278
  </fieldset>
279
  </div>';
280
  }
281
 
282
  /**
283
+ * Counter mode option.
284
+ */
285
  public function counter_mode() {
286
  echo '
287
  <div id="pvc_counter_mode">
288
  <fieldset>';
289
 
290
+ foreach ( $this->modes as $key => $value ) {
291
+ $key = esc_attr( $key );
292
 
293
  echo '
294
+ <input id="pvc-counter-mode-' . $key . '" type="radio" name="post_views_counter_settings_general[counter_mode]" value="' . $key . '" ' . checked( $key, Post_Views_Counter()->get_attribute( 'options', 'general', 'counter_mode' ), false ) . ' /><label for="pvc-counter-mode-' . $key . '">' . esc_html( $value ) . '</label>';
295
  }
296
 
297
  echo '
298
  <br/>
299
+ <span class="description">' . esc_html__( 'Select the method of collecting post views data. If you are using any of the caching plugins select Javascript.', 'post-views-counter' ) . '</span>
300
  </fieldset>
301
  </div>';
302
  }
303
 
304
  /**
305
+ * Post views column option.
306
+ */
307
+ public function post_views_column() {
308
  echo '
309
  <div id="pvc_post_views_column">
310
  <fieldset>';
311
 
312
+ foreach ( $this->choices as $key => $value ) {
313
+ $key = esc_attr( $key );
314
 
315
  echo '
316
+ <input id="pvc-post-views-column-' . $key . '" type="radio" name="post_views_counter_settings_general[post_views_column]" value="' . $key . '" ' . checked( $key, (Post_Views_Counter()->get_attribute( 'options', 'general', 'post_views_column' ) === true ? 'yes' : 'no' ), false ) . ' /><label for="pvc-post-views-column-' . $key . '">' . esc_html( $value ) . '</label>';
317
  }
318
 
319
  echo '
320
  <br/>
321
+ <span class="description">' . esc_html__( 'Enable to display post views count column for each of the selected post types.', 'post-views-counter' ) . '</span>
322
  </fieldset>
323
  </div>';
324
  }
325
 
326
  /**
327
+ * Time between counts option.
328
+ */
329
  public function time_between_counts() {
330
  echo '
331
  <div id="pvc_time_between_counts">
332
  <fieldset>
333
+ <input size="4" type="text" name="post_views_counter_settings_general[time_between_counts][number]" value="' . esc_attr( Post_Views_Counter()->get_attribute( 'options', 'general', 'time_between_counts', 'number' ) ) . '" />
334
  <select class="pvc-chosen-short" name="post_views_counter_settings_general[time_between_counts][type]">';
335
 
336
+ foreach ( $this->time_types as $type => $type_name ) {
337
  echo '
338
+ <option value="' . esc_attr( $type ) . '" ' . selected( $type, Post_Views_Counter()->get_attribute( 'options', 'general', 'time_between_counts', 'type' ), false ) . '>' . esc_html( $type_name ) . '</option>';
339
  }
340
 
341
  echo '
342
  </select>
343
  <br/>
344
+ <span class="description">' . esc_html__( 'Enter the time between single user visit count.', 'post-views-counter' ) . '</span>
345
  </fieldset>
346
  </div>';
347
  }
348
 
349
  /**
350
+ * Reset counts option.
351
+ */
352
+ public function reset_counts() {
 
353
  echo '
354
  <div id="pvc_reset_counts">
355
  <fieldset>
356
+ <input size="4" type="text" name="post_views_counter_settings_general[reset_counts][number]" value="' . esc_attr( Post_Views_Counter()->get_attribute( 'options', 'general', 'reset_counts', 'number' ) ) . '" />
357
  <select class="pvc-chosen-short" name="post_views_counter_settings_general[reset_counts][type]">';
358
 
359
+ foreach ( $this->time_types as $type => $type_name ) {
360
  echo '
361
+ <option value="' . esc_attr( $type ) . '" ' . selected( $type, Post_Views_Counter()->get_attribute( 'options', 'general', 'reset_counts', 'type' ), false ) . '>' . esc_html( $type_name ) . '</option>';
362
  }
363
 
364
  echo '
365
  </select>
366
  <br/>
367
+ <span class="description">' . esc_html__( 'Delete single day post views data older than specified above. Enter 0 (number zero) if you want to preserve your data regardless of its age.', 'post-views-counter' ) . '</span>
368
  </fieldset>
369
  </div>';
370
  }
371
 
372
  /**
373
+ * Flush interval option.
374
+ */
375
  public function flush_interval() {
376
  echo '
377
  <div id="pvc_flush_interval">
378
  <fieldset>
379
+ <input size="4" type="text" name="post_views_counter_settings_general[flush_interval][number]" value="' . esc_attr( Post_Views_Counter()->get_attribute( 'options', 'general', 'flush_interval', 'number' ) ) . '" />
380
  <select class="pvc-chosen-short" name="post_views_counter_settings_general[flush_interval][type]">';
381
 
382
+ foreach ( $this->time_types as $type => $type_name ) {
383
  echo '
384
+ <option value="' . esc_attr( $type ) . '" ' . selected( $type, Post_Views_Counter()->get_attribute( 'options', 'general', 'flush_interval', 'type' ), false ) . '>' . esc_html( $type_name ) . '</option>';
385
  }
386
 
387
  echo '
388
  </select>
389
  <br/>
390
+ <span class="description">' . __( 'How often to flush cached view counts from the object cache into the database. This feature is used only if a persistent object cache is detected and the interval is greater than 0 (number zero)). When used, view counts will be collected and stored in the object cache instead of the database and will then be asynchronously flushed to the database according to the specified interval.<br /><strong>Notice:</strong> Potential data loss may occur if the object cache is cleared/unavailable for the duration of the interval.', 'post-views-counter' ) . '</span>
391
  </fieldset>
392
  </div>';
393
  }
394
 
395
  /**
396
+ * Exlude user groups option.
397
+ */
398
  public function exclude() {
399
  echo '
400
  <div id="pvc_exclude">
401
  <fieldset>
402
+ <select class="pvc-chosen" data-placeholder="' . esc_attr__( 'Select groups', 'post-views-counter' ) . '" name="post_views_counter_settings_general[exclude][groups][]" multiple="multiple">';
403
 
404
+ foreach ( $this->groups as $type => $type_name ) {
405
  echo '
406
+ <option value="' . esc_attr( $type ) . '" ' . selected( in_array( $type, Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude', 'groups' ), true ), true, false ) . '>' . esc_html( $type_name ) . '</option>';
407
  }
408
 
409
  echo '
410
  </select>
411
  <br/>
412
+ <div class="pvc_user_roles"' . (in_array( 'roles', Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude', 'groups' ), true ) ? '' : ' style="display: none;"') . '>
413
+ <select class="pvc-chosen" data-placeholder="' . esc_attr__( 'Select user roles', 'post-views-counter' ) . '" name="post_views_counter_settings_general[exclude][roles][]" multiple="multiple">';
414
 
415
+ foreach ( $this->user_roles as $role => $role_name ) {
416
  echo '
417
+ <option value="' . esc_attr( $role ) . '" ' . selected( in_array( $role, Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude', 'roles' ), true ), true, false ) . '>' . esc_html( $role_name ) . '</option>';
418
  }
419
 
420
  echo '
421
  </select>
422
  <br/>
423
  </div>
424
+ <span class="description">' . esc_html__( 'Select the type of visitors to be excluded from post views count.', 'post-views-counter' ) . '</span>
425
  </fieldset>
426
  </div>';
427
  }
428
 
429
  /**
430
+ * Exclude IPs option.
431
+ */
432
  public function exclude_ips() {
433
  echo '
434
  <div id="pvc_exclude_ips">
435
  <fieldset>';
436
 
437
+ foreach ( Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude_ips' ) as $key => $ip ) {
438
  echo '
439
  <div class="ip-box">
440
+ <input type="text" name="post_views_counter_settings_general[exclude_ips][]" value="' . esc_attr( $ip ) . '" /> <input type="button" class="button button-secondary remove-exclude-ip" value="' . esc_attr__( 'Remove', 'post-views-counter' ) . '" />
441
  </div>';
442
  }
443
 
444
  // lovely php 5.2 limitations
445
+ $ips = Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude_ips' );
446
 
447
  echo '
448
  <div class="ip-box">
449
+ <input type="text" name="post_views_counter_settings_general[exclude_ips][]" value="" /> <input type="button" class="button button-secondary remove-exclude-ip" value="' . esc_attr__( 'Remove', 'post-views-counter' ) . '"' . (empty( $ips ) ? ' style="display: none;"' : '') . ' /> <input type="button" class="button button-secondary add-exclude-ip" value="' . esc_attr__( 'Add new', 'post-views-counter' ) . '" /> <input type="button" class="button button-secondary add-current-ip" value="' . esc_attr__( 'Add my current IP', 'post-views-counter' ) . '" data-rel="' . esc_attr( $_SERVER['REMOTE_ADDR'] ) . '" />
450
  </div>
451
+ <span class="description">' . esc_html__( 'Enter the IP addresses to be excluded from post views count.', 'post-views-counter' ) . '</span>
452
  </fieldset>
453
  </div>';
454
  }
455
 
456
  /**
457
+ * WP-PostViews import option.
458
+ */
459
  public function wp_postviews() {
460
  echo '
461
  <div id="pvc_wp_postviews">
462
  <fieldset>
463
+ <input type="submit" class="button button-secondary" name="post_views_counter_import_wp_postviews" value="' . __( 'Import', 'post-views-counter' ) . '"/>
464
  <br/>
465
+ <p class="description">' . esc_html__( 'Import post views data from WP-PostViews plugin.', 'post-views-counter' ) . '</p>
466
+ <input id="pvc-wp-postviews" type="checkbox" name="post_views_counter_import_wp_postviews_override"/><label for="pvc-wp-postviews">' . esc_html__( 'Override existing Post Views Counter data.', 'post-views-counter' ) . '</label>
467
  </fieldset>
468
  </div>';
469
  }
470
 
471
  /**
472
+ * Plugin deactivation option.
473
+ */
474
  public function deactivation_delete() {
475
  echo '
476
  <div id="pvc_deactivation_delete">
477
  <fieldset>';
478
 
479
+ foreach ( $this->choices as $key => $value ) {
480
+ $key = esc_attr( $key );
481
 
482
  echo '
483
+ <input id="pvc-deactivation-delete-' . $key . '" type="radio" name="post_views_counter_settings_general[deactivation_delete]" value="' . $key . '" ' . checked( $key, (Post_Views_Counter()->get_attribute( 'options', 'general', 'deactivation_delete' ) === true ? 'yes' : 'no' ), false ) . ' /><label for="pvc-deactivation-delete-' . $key . '">' . esc_html( $value ) . '</label>';
484
  }
485
 
486
  echo '
487
  <br/>
488
+ <span class="description">' . esc_html__( 'Enable to delete all plugin data on deactivation.', 'post-views-counter' ) . '</span>
489
  </fieldset>
490
  </div>';
491
  }
492
 
493
  /**
494
+ * Counter position option.
495
+ */
496
  public function position() {
497
  echo '
498
  <div id="pvc_position">
499
  <fieldset>
500
  <select class="pvc-chosen-short" name="post_views_counter_settings_display[position]">';
501
 
502
+ foreach ( $this->positions as $position => $position_name ) {
503
  echo '
504
+ <option value="' . esc_attr( $position ) . '" ' . selected( $position, Post_Views_Counter()->get_attribute( 'options', 'display', 'position' ), false ) . '>' . esc_html( $position_name ) . '</option>';
505
  }
506
 
507
  echo '
508
  </select>
509
  <br/>
510
+ <span class="description">' . esc_html__( 'Select where would you like to display the post views counter. Use [post-views] shortcode for manual display.', 'post-views-counter' ) . '</span>
511
  </fieldset>
512
  </div>';
513
  }
514
 
515
  /**
516
+ * Counter style option.
517
+ */
518
+ public function display_style() {
519
  echo '
520
  <div id="pvc_display_style">
521
  <fieldset>';
522
 
523
+ foreach ( $this->display_styles as $display => $style ) {
524
+ $display = esc_attr( $display );
525
 
526
  echo '
527
+ <input id="pvc-display-style-' . $display . '" type="checkbox" name="post_views_counter_settings_display[display_style][' . $display . ']" value="' . $display . '" ' . checked( true, Post_Views_Counter()->get_attribute( 'options', 'display', 'display_style', $display ), false ) . ' /><label for="pvc-display-style-' . $display . '">' . esc_html( $style ) . '</label>';
528
  }
529
 
530
  echo '
531
  <br/>
532
+ <span class="description">' . esc_html__( 'Choose how to display the post views counter.', 'post-views-counter' ) . '</span>
533
  </fieldset>
534
  </div>';
535
  }
536
 
537
  /**
538
+ * Counter icon class option.
539
+ */
540
  public function icon_class() {
541
  echo '
542
  <div id="pvc_icon_class">
543
  <fieldset>
544
+ <input type="text" name="post_views_counter_settings_display[icon_class]" class="large-text" value="' . esc_attr( Post_Views_Counter()->get_attribute( 'options', 'display', 'icon_class' ) ) . '"/>
545
  <br/>
546
+ <span class="description">' . sprintf( __( 'Enter the post views icon class. Any of the <a href="%s" target="_blank">Dashicons</a> classes are available.', 'post-views-counter' ), 'http://melchoyce.github.io/dashicons/' ) . '</span>
547
  </fieldset>
548
  </div>';
549
  }
550
 
 
551
  /**
552
+ * Restrict display option.
553
+ */
554
  public function restrict_display() {
555
  echo '
556
  <div id="pvc_restrict_display">
557
  <fieldset>
558
+ <select class="pvc-chosen" data-placeholder="' . esc_attr__( 'Select groups', 'post-views-counter' ) . '" name="post_views_counter_settings_display[restrict_display][groups][]" multiple="multiple">';
559
+
560
+ foreach ( $this->groups as $type => $type_name ) {
561
 
562
+ if ( $type === 'robots' )
 
 
563
  continue;
564
 
565
  echo '
566
+ <option value="' . esc_attr( $type ) . '" ' . selected( in_array( $type, Post_Views_Counter()->get_attribute( 'options', 'display', 'restrict_display', 'groups' ), true ), true, false ) . '>' . esc_html( $type_name ) . '</option>';
567
  }
568
 
569
  echo '
570
  </select>
571
  <br/>
572
+ <div class="pvc_user_roles"' . (in_array( 'roles', Post_Views_Counter()->get_attribute( 'options', 'display', 'restrict_display', 'groups' ), true ) ? '' : ' style="display: none;"') . '>
573
+ <select class="pvc-chosen" data-placeholder="' . esc_attr__( 'Select user roles', 'post-views-counter' ) . '" name="post_views_counter_settings_display[restrict_display][roles][]" multiple="multiple">';
574
 
575
+ foreach ( $this->user_roles as $role => $role_name ) {
576
  echo '
577
+ <option value="' . esc_attr( $role ) . '" ' . selected( in_array( $role, Post_Views_Counter()->get_attribute( 'options', 'display', 'restrict_display', 'roles' ), true ), true, false ) . '>' . esc_html( $role_name ) . '</option>';
578
  }
579
 
580
  echo '
581
  </select>
582
  <br/>
583
  </div>
584
+ <span class="description">' . esc_html__( 'Use it to hide the post views counter from selected type of visitors.', 'post-views-counter' ) . '</span>
585
  </fieldset>
586
  </div>';
587
  }
588
 
 
589
  /**
590
+ * Validate general settings.
591
+ */
592
+ public function validate_settings( $input ) {
593
+ if ( isset( $_POST['post_views_counter_import_wp_postviews'] ) ) {
594
  global $wpdb;
595
 
596
  $views = $wpdb->get_results(
597
+ "SELECT post_id, meta_value FROM " . $wpdb->postmeta . " WHERE meta_key = 'views'", ARRAY_A, 0
 
 
598
  );
599
 
600
+ if ( ! empty( $views ) ) {
601
+ $input = Post_Views_Counter()->get_attribute( 'defaults', 'general' );
602
  $input['wp_postviews_import'] = true;
603
 
604
  $sql = '';
605
 
606
+ foreach ( $views as $view ) {
607
+ $sql[] = "(" . $view['post_id'] . ", 4, 'total', " . $view['meta_value'] . ")";
608
  }
609
 
610
+ $wpdb->query( "INSERT INTO " . $wpdb->prefix . "post_views(id, type, period, count) VALUES " . implode( ',', $sql ) . " ON DUPLICATE KEY UPDATE count = " . (isset( $_POST['post_views_counter_import_wp_postviews_override'] ) ? '' : 'count + ') . "VALUES(count)" );
611
 
612
+ add_settings_error( 'wp_postviews_import', 'wp_postviews_import', __( 'WP-PostViews data imported succesfully.', 'post-views-counter' ), 'updated' );
613
  } else {
614
+ add_settings_error( 'wp_postviews_import', 'wp_postviews_import', __( 'There was no data to import.', 'post-views-counter' ), 'updated' );
615
  }
616
+ } elseif ( isset( $_POST['save_pvc_general'] ) ) {
 
617
  // post types count
618
+ if ( isset( $input['post_types_count'] ) ) {
619
  $post_types = array();
620
 
621
+ foreach ( $input['post_types_count'] as $post_type ) {
622
+ if ( isset( $this->post_types[$post_type] ) )
623
  $post_types[] = $post_type;
624
  }
625
 
626
+ $input['post_types_count'] = array_unique( $post_types );
627
+ } else
 
628
  $input['post_types_count'] = array();
629
 
630
  // counter mode
631
+ $input['counter_mode'] = (isset( $input['counter_mode'], $this->modes[$input['counter_mode']] ) ? $input['counter_mode'] : Post_Views_Counter()->get_attribute( 'defaults', 'general', 'counter_mode' ));
632
 
633
  // post views column
634
+ $input['post_views_column'] = (isset( $input['post_views_column'], $this->choices[$input['post_views_column']] ) ? ($input['post_views_column'] === 'yes' ? true : false) : Post_Views_Counter()->get_attribute( 'defaults', 'general', 'post_views_column' ));
635
 
636
  // time between counts
637
+ $input['time_between_counts']['number'] = (int) (isset( $input['time_between_counts']['number'] ) ? $input['time_between_counts']['number'] : Post_Views_Counter()->get_attribute( 'defaults', 'general', 'time_between_counts', 'number' ));
638
+ $input['time_between_counts']['type'] = (isset( $input['time_between_counts']['type'], $this->time_types[$input['time_between_counts']['type']] ) ? $input['time_between_counts']['type'] : Post_Views_Counter()->get_attribute( 'defaults', 'general', 'time_between_counts', 'type' ));
639
 
640
  // flush interval
641
+ $input['flush_interval']['number'] = (int) (isset( $input['flush_interval']['number'] ) ? $input['flush_interval']['number'] : Post_Views_Counter()->get_attribute( 'defaults', 'general', 'flush_interval', 'number' ));
642
+ $input['flush_interval']['type'] = (isset( $input['flush_interval']['type'], $this->time_types[$input['flush_interval']['type']] ) ? $input['flush_interval']['type'] : Post_Views_Counter()->get_attribute( 'defaults', 'general', 'flush_interval', 'type' ));
643
+
644
  // Since the settings are about to be saved and cache flush interval could've changed,
645
  // we want to make sure that any changes done on the settings page are in effect immediately
646
  // (instead of having to wait for the previous schedule to occur).
647
  // We achieve that by making sure to clear any previous cache flush schedules and
648
  // schedule the new one if the specified interval is > 0
649
  Post_Views_Counter()->remove_cache_flush();
650
+
651
  if ( $input['flush_interval']['number'] > 0 ) {
652
  Post_Views_Counter()->schedule_cache_flush();
653
  }
654
 
655
  // reset counts
656
+ $input['reset_counts']['number'] = (int) (isset( $input['reset_counts']['number'] ) ? $input['reset_counts']['number'] : Post_Views_Counter()->get_attribute( 'defaults', 'general', 'reset_counts', 'number' ));
657
+ $input['reset_counts']['type'] = (isset( $input['reset_counts']['type'], $this->time_types[$input['reset_counts']['type']] ) ? $input['reset_counts']['type'] : Post_Views_Counter()->get_attribute( 'defaults', 'general', 'reset_counts', 'type' ));
658
 
659
  // run cron on next visit?
660
  $input['cron_run'] = ($input['reset_counts']['number'] > 0 ? true : false);
661
+ $input['cron_update'] = ($input['cron_run'] && (Post_Views_Counter()->get_attribute( 'options', 'general', 'reset_counts', 'number' ) !== $input['reset_counts']['number'] || Post_Views_Counter()->get_attribute( 'options', 'general', 'reset_counts', 'type' ) !== $input['reset_counts']['type']) ? true : false);
662
 
663
  // exclude
664
+ if ( isset( $input['exclude']['groups'] ) ) {
665
  $groups = array();
666
 
667
+ foreach ( $input['exclude']['groups'] as $group ) {
668
+ if ( isset( $this->groups[$group] ) )
669
  $groups[] = $group;
670
  }
671
 
672
+ $input['exclude']['groups'] = array_unique( $groups );
673
  } else
674
  $input['exclude']['groups'] = array();
675
 
676
+ if ( in_array( 'roles', $input['exclude']['groups'], true ) && isset( $input['exclude']['roles'] ) ) {
677
  $roles = array();
678
 
679
+ foreach ( $input['exclude']['roles'] as $role ) {
680
+ if ( isset( $this->user_roles[$role] ) )
 
681
  $roles[] = $role;
682
  }
683
 
684
+ $input['exclude']['roles'] = array_unique( $roles );
685
  } else
686
  $input['exclude']['roles'] = array();
687
 
688
  // exclude ips
689
+ if ( isset( $input['exclude_ips'] ) ) {
690
+
691
  $ips = array();
692
 
693
+ foreach ( $input['exclude_ips'] as $ip ) {
694
+ if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) )
695
  $ips[] = $ip;
696
  }
697
 
698
+ $input['exclude_ips'] = array_unique( $ips );
699
  }
700
 
701
  // deactivation delete
702
+ $input['deactivation_delete'] = (isset( $input['deactivation_delete'], $this->choices[$input['deactivation_delete']] ) ? ($input['deactivation_delete'] === 'yes' ? true : false) : Post_Views_Counter()->get_attribute( 'defaults', 'general', 'deactivation_delete' ));
703
+ } elseif ( isset( $_POST['save_pvc_display'] ) ) {
704
+
 
705
  // post views label
706
+ $input['label'] = (isset( $input['label'] ) ? $input['label'] : Post_Views_Counter()->get_attribute( 'defaults', 'general', 'label' ));
707
 
708
+ if ( function_exists( 'icl_register_string' ) )
709
+ icl_register_string( 'Post Views Counter', 'Post Views Label', $input['label'] );
710
 
711
  // position
712
+ $input['position'] = (isset( $input['position'], $this->positions[$input['position']] ) ? $input['position'] : Post_Views_Counter()->get_attribute( 'defaults', 'general', 'position' ));
713
 
714
  // display style
715
+ $input['display_style']['icon'] = (isset( $input['display_style']['icon'] ) ? true : false);
716
+ $input['display_style']['text'] = (isset( $input['display_style']['text'] ) ? true : false);
717
 
718
  // link to post
719
+ $input['link_to_post'] = (isset( $input['link_to_post'], $this->choices[$input['link_to_post']] ) ? ($input['link_to_post'] === 'yes' ? true : false) : Post_Views_Counter()->get_attribute( 'defaults', 'general', 'link_to_post' ));
720
 
721
  // icon class
722
+ $input['icon_class'] = (isset( $input['icon_class'] ) ? trim( $input['icon_class'] ) : Post_Views_Counter()->get_attribute( 'defaults', 'general', 'icon_class' ));
723
 
724
  // post types display
725
+ if ( isset( $input['post_types_display'] ) ) {
726
  $post_types = array();
727
 
728
+ foreach ( $input['post_types_display'] as $post_type ) {
729
+ if ( isset( $this->post_types[$post_type] ) )
 
730
  $post_types[] = $post_type;
731
  }
732
 
733
+ $input['post_types_display'] = array_unique( $post_types );
734
  } else
735
  $input['post_types_display'] = array();
736
 
737
  // restrict display
738
+ if ( isset( $input['restrict_display']['groups'] ) ) {
739
  $groups = array();
740
 
741
+ foreach ( $input['restrict_display']['groups'] as $group ) {
742
+ if ( $group === 'robots' )
743
  continue;
744
 
745
+ if ( isset( $this->groups[$group] ) )
746
  $groups[] = $group;
747
  }
748
 
749
+ $input['restrict_display']['groups'] = array_unique( $groups );
750
  } else
751
  $input['restrict_display']['groups'] = array();
752
 
753
+ if ( in_array( 'roles', $input['restrict_display']['groups'], true ) && isset( $input['restrict_display']['roles'] ) ) {
754
  $roles = array();
755
 
756
+ foreach ( $input['restrict_display']['roles'] as $role ) {
757
+ if ( isset( $this->user_roles[$role] ) )
758
  $roles[] = $role;
759
  }
760
 
761
+ $input['restrict_display']['roles'] = array_unique( $roles );
762
  } else
763
  $input['restrict_display']['roles'] = array();
764
+ } elseif ( isset( $_POST['reset_pvc_general'] ) ) {
765
+ $input = Post_Views_Counter()->get_attribute( 'defaults', 'general' );
766
 
767
+ add_settings_error( 'reset_general_settings', 'settings_reset', __( 'General settings restored to defaults.', 'post-views-counter' ), 'updated' );
768
+ } elseif ( isset( $_POST['reset_pvc_display'] ) ) {
769
+ $input = Post_Views_Counter()->get_attribute( 'defaults', 'display' );
770
 
771
+ add_settings_error( 'reset_general_settings', 'settings_reset', __( 'Display settings restored to defaults.', 'post-views-counter' ), 'updated' );
772
  }
773
 
774
  return $input;
775
  }
776
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
777
  }
 
includes/update.php CHANGED
@@ -1,30 +1,31 @@
1
  <?php
2
- if(!defined('ABSPATH')) exit;
 
3
 
4
  new Post_Views_Counter_Update();
5
 
6
  class Post_Views_Counter_Update {
7
-
8
  public function __construct() {
9
  // actions
10
- add_action('init', array(&$this, 'check_update'));
11
  }
12
 
13
  /**
14
  * Check if there's a db update required
15
- */
16
  public function check_update() {
17
- if(!current_user_can('manage_options'))
18
  return;
19
 
20
  // get current database version
21
- $current_db_version = get_option('post_views_counter_version', '1.0.0');
22
 
23
  // new version?
24
- if(version_compare($current_db_version, Post_Views_Counter()->get_attribute('defaults', 'version'), '<')) {
25
  // update plugin version
26
- update_option('post_views_counter_version', Post_Views_Counter()->get_attribute('defaults', 'version'));
27
  }
28
  }
 
29
  }
30
- ?>
1
  <?php
2
+ if ( ! defined( 'ABSPATH' ) )
3
+ exit;
4
 
5
  new Post_Views_Counter_Update();
6
 
7
  class Post_Views_Counter_Update {
8
+
9
  public function __construct() {
10
  // actions
11
+ add_action( 'init', array( &$this, 'check_update' ) );
12
  }
13
 
14
  /**
15
  * Check if there's a db update required
16
+ */
17
  public function check_update() {
18
+ if ( ! current_user_can( 'manage_options' ) )
19
  return;
20
 
21
  // get current database version
22
+ $current_db_version = get_option( 'post_views_counter_version', '1.0.0' );
23
 
24
  // new version?
25
+ if ( version_compare( $current_db_version, Post_Views_Counter()->get_attribute( 'defaults', 'version' ), '<' ) ) {
26
  // update plugin version
27
+ update_option( 'post_views_counter_version', Post_Views_Counter()->get_attribute( 'defaults', 'version' ) );
28
  }
29
  }
30
+
31
  }
 
includes/widgets.php CHANGED
@@ -1,25 +1,27 @@
1
  <?php
2
- if(!defined('ABSPATH')) exit;
 
3
 
4
  new Post_Views_Counter_Widgets();
5
 
6
  class Post_Views_Counter_Widgets {
7
-
8
  public function __construct() {
9
  // actions
10
- add_action('widgets_init', array(&$this, 'register_widgets'));
11
  }
12
 
13
  /**
14
  * Register PVC widget
15
- */
16
  public function register_widgets() {
17
- register_widget('Post_Views_Counter_List_Widget');
18
  }
 
19
  }
20
 
21
  class Post_Views_Counter_List_Widget extends WP_Widget {
22
-
23
  private $pvc_options;
24
  private $pvc_defaults;
25
  private $pvc_post_types;
@@ -28,57 +30,55 @@ class Post_Views_Counter_List_Widget extends WP_Widget {
28
 
29
  public function __construct() {
30
  parent::__construct(
31
- 'Post_Views_Counter_List_Widget',
32
- __('Most Viewed Posts', 'post-views-counter'),
33
- array(
34
- 'description' => __('Displays a list of the most viewed posts', 'post-views-counter')
35
  )
36
  );
37
 
38
  $this->pvc_options = array_merge(
39
- array('general' => get_option('events_maker_general'))
40
  );
41
 
42
  $this->pvc_defaults = array(
43
- 'title' => __('Most Viewed Posts', 'post-views-counter'),
44
- 'number_of_posts' => 5,
45
- 'thumbnail_size' => 'thumbnail',
46
- 'post_types' => array(),
47
- 'order' => 'desc',
48
- 'show_post_views' => true,
49
- 'show_post_thumbnail' => false,
50
- 'show_post_excerpt' => false,
51
- 'no_posts_message' => __('No Posts found', 'post-views-counter')
52
  );
53
 
54
  $this->pvc_order_types = array(
55
- 'asc' => __('Ascending', 'post-views-counter'),
56
- 'desc' => __('Descending', 'post-views-counter')
57
  );
58
 
59
- $this->pvc_image_sizes = array_merge(array('full'), get_intermediate_image_sizes());
60
 
61
  // sort image sizes by name, ascending
62
- sort($this->pvc_image_sizes, SORT_STRING);
63
 
64
- add_action('wp_loaded', array(&$this, 'load_post_types'));
65
  }
66
 
67
  /**
68
  * Get selected post types
69
- */
70
  public function load_post_types() {
71
- $this->pvc_post_types = Post_Views_Counter()->get_instance('settings')->post_types;
72
  }
73
 
74
  /**
75
  * Display widget function
76
- */
77
- public function widget($args, $instance) {
78
- $instance['title'] = apply_filters('widget_title', $instance['title'], $instance, $this->id_base);
79
 
80
- $html = $args['before_widget'].(!empty($instance['title']) ? $args['before_title'].$instance['title'].$args['after_title'] : '');
81
- $html .= pvc_most_viewed_posts($instance, false);
82
  $html .= $args['after_widget'];
83
 
84
  echo $html;
@@ -86,62 +86,62 @@ class Post_Views_Counter_List_Widget extends WP_Widget {
86
 
87
  /**
88
  * Admin widget function
89
- */
90
- public function form($instance) {
91
  $html = '
92
  <p>
93
- <label for="'.$this->get_field_id('title').'">'.__('Title', 'post-views-counter').':</label>
94
- <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']).'" />
95
  </p>
96
  <p>
97
- <label>'.__('Post Types', 'post-views-counter').':</label><br />';
98
 
99
- foreach ($this->pvc_post_types as $post_type => $post_type_name) {
100
- $html .= '
101
- <input id="'.$this->get_field_id('post_types').'-'.$post_type.'" type="checkbox" name="'.$this->get_field_name('post_types').'[]" value="'.$post_type.'" '.checked((!isset($instance['post_types']) ? true : in_array($post_type, $instance['post_types'], true)), true, false).'><label for="'.$this->get_field_id('post_types').'-'.$post_type.'">'.esc_html($post_type_name).'</label>';
102
  }
103
 
104
- $show_post_thumbnail = (isset($instance['show_post_thumbnail']) ? $instance['show_post_thumbnail'] : $this->pvc_defaults['show_post_thumbnail']);
105
 
106
- $html .= '
107
  </select>
108
  </p>
109
  <p>
110
- <label for="'.$this->get_field_id('number_of_posts').'">'.__('Number of posts to show', 'post-views-counter').':</label>
111
- <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']).'" />
112
  </p>
113
  <p>
114
- <label for="'.$this->get_field_id('no_posts_message').'">'.__('No posts message', 'post-views-counter').':</label>
115
- <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']).'" />
116
  </p>
117
  <p>
118
- <label for="'.$this->get_field_id('order').'">'.__('Order', 'post-views-counter').':</label>
119
- <select id="'.$this->get_field_id('order').'" name="'.$this->get_field_name('order').'">';
120
 
121
- foreach ($this->pvc_order_types as $id => $order) {
122
  $html .= '
123
- <option value="'.esc_attr($id).'" '.selected($id, (isset($instance['order']) ? $instance['order'] : $this->pvc_defaults['order']), false).'>'.$order.'</option>';
124
  }
125
 
126
  $html .= '
127
  </select>
128
  </p>
129
  <p>
130
- <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>
131
  <br />
132
- <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>
133
  <br />
134
- <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>
135
  </p>
136
- <p class="em-event-thumbnail-size"'.($show_post_thumbnail ? '' : ' style="display: none;"').'>
137
- <label for="'.$this->get_field_id('thumbnail_size').'">'.__('Thumbnail size', 'post-views-counter').':</label>
138
- <select id="'.$this->get_field_id('thumbnail_size').'" name="'.$this->get_field_name('thumbnail_size').'">';
139
 
140
- $size_type = (isset($instance['thumbnail_size']) ? $instance['thumbnail_size'] : $this->pvc_defaults['thumbnail_size']);
141
 
142
- foreach ($this->pvc_image_sizes as $size) {
143
  $html .= '
144
- <option value="'.esc_attr($size).'" '.selected($size, $size_type, false).'>'.$size.'</option>';
145
  }
146
 
147
  $html .= '
@@ -153,41 +153,40 @@ class Post_Views_Counter_List_Widget extends WP_Widget {
153
 
154
  /**
155
  * Save widget function
156
- */
157
- public function update($new_instance, $old_instance) {
158
  // number of posts
159
- $old_instance['number_of_posts'] = (int)(isset($new_instance['number_of_posts']) ? $new_instance['number_of_posts'] : $this->pvc_defaults['number_of_posts']);
160
 
161
  // order
162
- $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']);
163
 
164
  // thumbnail size
165
- $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']);
166
 
167
  // booleans
168
- $old_instance['show_post_views'] = (isset($new_instance['show_post_views']) ? true : false);
169
- $old_instance['show_post_thumbnail'] = (isset($new_instance['show_post_thumbnail']) ? true : false);
170
- $old_instance['show_post_excerpt'] = (isset($new_instance['show_post_excerpt']) ? true : false);
171
 
172
  // texts
173
- $old_instance['title'] = sanitize_text_field(isset($new_instance['title']) ? $new_instance['title'] : $this->pvc_defaults['title']);
174
- $old_instance['no_posts_message'] = sanitize_text_field(isset($new_instance['no_posts_message']) ? $new_instance['no_posts_message'] : $this->pvc_defaults['no_posts_message']);
175
 
176
  // post types
177
- if (isset($new_instance['post_types'])) {
178
  $post_types = array();
179
 
180
- foreach ($new_instance['post_types'] as $post_type) {
181
- if (isset($this->pvc_post_types[$post_type]))
182
  $post_types[] = $post_type;
183
  }
184
 
185
- $old_instance['post_types'] = array_unique($post_types);
186
- }
187
- else
188
- $old_instance['post_types'] = array('post');
189
 
190
  return $old_instance;
191
  }
 
192
  }
193
- ?>
1
  <?php
2
+ if ( ! defined( 'ABSPATH' ) )
3
+ exit;
4
 
5
  new Post_Views_Counter_Widgets();
6
 
7
  class Post_Views_Counter_Widgets {
8
+
9
  public function __construct() {
10
  // actions
11
+ add_action( 'widgets_init', array( &$this, 'register_widgets' ) );
12
  }
13
 
14
  /**
15
  * Register PVC widget
16
+ */
17
  public function register_widgets() {
18
+ register_widget( 'Post_Views_Counter_List_Widget' );
19
  }
20
+
21
  }
22
 
23
  class Post_Views_Counter_List_Widget extends WP_Widget {
24
+
25
  private $pvc_options;
26
  private $pvc_defaults;
27
  private $pvc_post_types;
30
 
31
  public function __construct() {
32
  parent::__construct(
33
+ 'Post_Views_Counter_List_Widget', __( 'Most Viewed Posts', 'post-views-counter' ), array(
34
+ 'description' => __( 'Displays a list of the most viewed posts', 'post-views-counter' )
 
 
35
  )
36
  );
37
 
38
  $this->pvc_options = array_merge(
39
+ array( 'general' => get_option( 'events_maker_general' ) )
40
  );
41
 
42
  $this->pvc_defaults = array(
43
+ 'title' => __( 'Most Viewed Posts', 'post-views-counter' ),
44
+ 'number_of_posts' => 5,
45
+ 'thumbnail_size' => 'thumbnail',
46
+ 'post_types' => array(),
47
+ 'order' => 'desc',
48
+ 'show_post_views' => true,
49
+ 'show_post_thumbnail' => false,
50
+ 'show_post_excerpt' => false,
51
+ 'no_posts_message' => __( 'No Posts found', 'post-views-counter' )
52
  );
53
 
54
  $this->pvc_order_types = array(
55
+ 'asc' => __( 'Ascending', 'post-views-counter' ),
56
+ 'desc' => __( 'Descending', 'post-views-counter' )
57
  );
58
 
59
+ $this->pvc_image_sizes = array_merge( array( 'full' ), get_intermediate_image_sizes() );
60
 
61
  // sort image sizes by name, ascending
62
+ sort( $this->pvc_image_sizes, SORT_STRING );
63
 
64
+ add_action( 'wp_loaded', array( &$this, 'load_post_types' ) );
65
  }
66
 
67
  /**
68
  * Get selected post types
69
+ */
70
  public function load_post_types() {
71
+ $this->pvc_post_types = Post_Views_Counter()->get_instance( 'settings' )->post_types;
72
  }
73
 
74
  /**
75
  * Display widget function
76
+ */
77
+ public function widget( $args, $instance ) {
78
+ $instance['title'] = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
79
 
80
+ $html = $args['before_widget'] . ( ! empty( $instance['title'] ) ? $args['before_title'] . $instance['title'] . $args['after_title'] : '');
81
+ $html .= pvc_most_viewed_posts( $instance, false );
82
  $html .= $args['after_widget'];
83
 
84
  echo $html;
86
 
87
  /**
88
  * Admin widget function
89
+ */
90
+ public function form( $instance ) {
91
  $html = '
92
  <p>
93
+ <label for="' . $this->get_field_id( 'title' ) . '">' . __( 'Title', 'post-views-counter' ) . ':</label>
94
+ <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'] ) . '" />
95
  </p>
96
  <p>
97
+ <label>' . __( 'Post Types', 'post-views-counter' ) . ':</label><br />';
98
 
99
+ foreach ( $this->pvc_post_types as $post_type => $post_type_name ) {
100
+ $html .= '
101
+ <input id="' . $this->get_field_id( 'post_types' ) . '-' . $post_type . '" type="checkbox" name="' . $this->get_field_name( 'post_types' ) . '[]" value="' . $post_type . '" ' . checked( ( ! isset( $instance['post_types'] ) ? true : in_array( $post_type, $instance['post_types'], true ) ), true, false ) . '><label for="' . $this->get_field_id( 'post_types' ) . '-' . $post_type . '">' . esc_html( $post_type_name ) . '</label>';
102
  }
103
 
104
+ $show_post_thumbnail = (isset( $instance['show_post_thumbnail'] ) ? $instance['show_post_thumbnail'] : $this->pvc_defaults['show_post_thumbnail']);
105
 
106
+ $html .= '
107
  </select>
108
  </p>
109
  <p>
110
+ <label for="' . $this->get_field_id( 'number_of_posts' ) . '">' . __( 'Number of posts to show', 'post-views-counter' ) . ':</label>
111
+ <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'] ) . '" />
112
  </p>
113
  <p>
114
+ <label for="' . $this->get_field_id( 'no_posts_message' ) . '">' . __( 'No posts message', 'post-views-counter' ) . ':</label>
115
+ <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'] ) . '" />
116
  </p>
117
  <p>
118
+ <label for="' . $this->get_field_id( 'order' ) . '">' . __( 'Order', 'post-views-counter' ) . ':</label>
119
+ <select id="' . $this->get_field_id( 'order' ) . '" name="' . $this->get_field_name( 'order' ) . '">';
120
 
121
+ foreach ( $this->pvc_order_types as $id => $order ) {
122
  $html .= '
123
+ <option value="' . esc_attr( $id ) . '" ' . selected( $id, (isset( $instance['order'] ) ? $instance['order'] : $this->pvc_defaults['order'] ), false ) . '>' . $order . '</option>';
124
  }
125
 
126
  $html .= '
127
  </select>
128
  </p>
129
  <p>
130
+ <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>
131
  <br />
132
+ <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>
133
  <br />
134
+ <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>
135
  </p>
136
+ <p class="em-event-thumbnail-size"' . ($show_post_thumbnail ? '' : ' style="display: none;"') . '>
137
+ <label for="' . $this->get_field_id( 'thumbnail_size' ) . '">' . __( 'Thumbnail size', 'post-views-counter' ) . ':</label>
138
+ <select id="' . $this->get_field_id( 'thumbnail_size' ) . '" name="' . $this->get_field_name( 'thumbnail_size' ) . '">';
139
 
140
+ $size_type = (isset( $instance['thumbnail_size'] ) ? $instance['thumbnail_size'] : $this->pvc_defaults['thumbnail_size']);
141
 
142
+ foreach ( $this->pvc_image_sizes as $size ) {
143
  $html .= '
144
+ <option value="' . esc_attr( $size ) . '" ' . selected( $size, $size_type, false ) . '>' . $size . '</option>';
145
  }
146
 
147
  $html .= '
153
 
154
  /**
155
  * Save widget function
156
+ */
157
+ public function update( $new_instance, $old_instance ) {
158
  // number of posts
159
+ $old_instance['number_of_posts'] = (int) (isset( $new_instance['number_of_posts'] ) ? $new_instance['number_of_posts'] : $this->pvc_defaults['number_of_posts']);
160
 
161
  // order
162
+ $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']);
163
 
164
  // thumbnail size
165
+ $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']);
166
 
167
  // booleans
168
+ $old_instance['show_post_views'] = (isset( $new_instance['show_post_views'] ) ? true : false);
169
+ $old_instance['show_post_thumbnail'] = (isset( $new_instance['show_post_thumbnail'] ) ? true : false);
170
+ $old_instance['show_post_excerpt'] = (isset( $new_instance['show_post_excerpt'] ) ? true : false);
171
 
172
  // texts
173
+ $old_instance['title'] = sanitize_text_field( isset( $new_instance['title'] ) ? $new_instance['title'] : $this->pvc_defaults['title'] );
174
+ $old_instance['no_posts_message'] = sanitize_text_field( isset( $new_instance['no_posts_message'] ) ? $new_instance['no_posts_message'] : $this->pvc_defaults['no_posts_message'] );
175
 
176
  // post types
177
+ if ( isset( $new_instance['post_types'] ) ) {
178
  $post_types = array();
179
 
180
+ foreach ( $new_instance['post_types'] as $post_type ) {
181
+ if ( isset( $this->pvc_post_types[$post_type] ) )
182
  $post_types[] = $post_type;
183
  }
184
 
185
+ $old_instance['post_types'] = array_unique( $post_types );
186
+ } else
187
+ $old_instance['post_types'] = array( 'post' );
 
188
 
189
  return $old_instance;
190
  }
191
+
192
  }
 
js/admin-post.js CHANGED
@@ -1,49 +1,49 @@
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');
20
- $('#post-views .edit-post-views').show();
21
-
22
- views = parseInt($('#post-views-input').val());
23
  // reassign value as integer
24
- $('#post-views-input').val(views);
25
-
26
- $('#post-views-display b').text(views);
27
-
28
  return false;
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');
37
- $('#post-views .edit-post-views').show();
38
-
39
- views = parseInt($('#post-views-current').val());
40
-
41
- $('#post-views-display b').text(views);
42
- $('#post-views-input').val(views);
43
-
44
  return false;
45
- });
46
-
47
- });
48
 
49
- })(jQuery);
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' );
20
+ $( '#post-views .edit-post-views' ).show();
21
+
22
+ views = parseInt( $( '#post-views-input' ).val() );
23
  // reassign value as integer
24
+ $( '#post-views-input' ).val( views );
25
+
26
+ $( '#post-views-display b' ).text( views );
27
+
28
  return false;
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' );
37
+ $( '#post-views .edit-post-views' ).show();
38
+
39
+ views = parseInt( $( '#post-views-current' ).val() );
40
+
41
+ $( '#post-views-display b' ).text( views );
42
+ $( '#post-views-input' ).val( views );
43
+
44
  return false;
45
+ } );
46
+
47
+ } );
48
 
49
+ } )( jQuery );
js/admin-settings.js CHANGED
@@ -1,93 +1,93 @@
1
- (function ($) {
2
-
3
- $(document).ready(function () {
4
-
5
- // default chosen
6
- $('.pvc-chosen').chosen({
7
- disable_search_threshold: 8,
8
- display_selected_options: false,
9
- search_contains: true,
10
- width: '300px'
11
- });
12
-
13
- // time types and position
14
- $('.pvc-chosen-short').chosen({
15
- disable_search_threshold: 8,
16
- width: '200px'
17
- });
18
-
19
- // ask whether to reset options to defaults
20
- $(document).on('click', '.reset_pvc_settings', function () {
21
- return confirm(pvcArgsSettings.resetToDefaults);
22
- });
23
-
24
- // remove ip box
25
- $(document).on('click', '.remove-exclude-ip', function () {
26
- var parent = $(this).parent(),
27
- nextParent = parent.parent(),
28
- addButton = parent.find('.add-exclude-ip').hide(),
29
- addCurrentIPButton = parent.find('.add-current-ip').hide();
30
-
31
- // remove ip box
32
- parent.remove();
33
-
34
- var children = nextParent.find('div');
35
-
36
- // was there add button?
37
- if (addButton.length === 1) {
38
- children.last().append(addButton.show(), ' ', addCurrentIPButton.show());
39
- // children.last().append();
40
- }
41
-
42
- // only one ip box left?
43
- if (children.length === 1) {
44
- children.find('.remove-exclude-ip').hide();
45
- }
46
- });
47
-
48
- // add ip box
49
- $(document).on('click', '.add-exclude-ip', function () {
50
- var parent = $(this).parent(),
51
- newBox = parent.clone().hide();
52
-
53
- // clear value
54
- newBox.find('input').first().val('');
55
-
56
- // remove add buttons
57
- $(this).remove();
58
- parent.find('.add-current-ip').remove();
59
-
60
- // add and display new ip box
61
- parent.after(newBox.show());
62
-
63
- parent.parent().find('.remove-exclude-ip').show();
64
- });
65
-
66
- // add current ip
67
- $(document).on('click', '.add-current-ip', function () {
68
- // fills input with user's current ip
69
- $(this).parent().find('input').first().val($(this).attr('data-rel'));
70
- });
71
-
72
- // display user roles if needed
73
- $(document).on('change', '.pvc-chosen-groups', function () {
74
- var foundRoles = false;
75
-
76
- // check whether roles are selected
77
- $(this).find(':selected').each(function (i, item) {
78
- if (item.value === 'roles') {
79
- foundRoles = true;
80
- }
81
- });
82
-
83
- // are roles selected?
84
- if (foundRoles) {
85
- $(this).parent().find('.pvc_user_roles').fadeIn(300);
86
- } else {
87
- $(this).parent().find('.pvc_user_roles').fadeOut(300);
88
- }
89
- });
90
-
91
- });
92
-
93
- })(jQuery);
1
+ ( function ( $ ) {
2
+
3
+ $( document ).ready( function () {
4
+
5
+ // default chosen
6
+ $( '.pvc-chosen' ).chosen( {
7
+ disable_search_threshold: 8,
8
+ display_selected_options: false,
9
+ search_contains: true,
10
+ width: '300px'
11
+ } );
12
+
13
+ // time types and position
14
+ $( '.pvc-chosen-short' ).chosen( {
15
+ disable_search_threshold: 8,
16
+ width: '200px'
17
+ } );
18
+
19
+ // ask whether to reset options to defaults
20
+ $( document ).on( 'click', '.reset_pvc_settings', function () {
21
+ return confirm( pvcArgsSettings.resetToDefaults );
22
+ } );
23
+
24
+ // remove ip box
25
+ $( document ).on( 'click', '.remove-exclude-ip', function () {
26
+ var parent = $( this ).parent(),
27
+ nextParent = parent.parent(),
28
+ addButton = parent.find( '.add-exclude-ip' ).hide(),
29
+ addCurrentIPButton = parent.find( '.add-current-ip' ).hide();
30
+
31
+ // remove ip box
32
+ parent.remove();
33
+
34
+ var children = nextParent.find( 'div' );
35
+
36
+ // was there add button?
37
+ if ( addButton.length === 1 ) {
38
+ children.last().append( addButton.show(), ' ', addCurrentIPButton.show() );
39
+ // children.last().append();
40
+ }
41
+
42
+ // only one ip box left?
43
+ if ( children.length === 1 ) {
44
+ children.find( '.remove-exclude-ip' ).hide();
45
+ }
46
+ } );
47
+
48
+ // add ip box
49
+ $( document ).on( 'click', '.add-exclude-ip', function () {
50
+ var parent = $( this ).parent(),
51
+ newBox = parent.clone().hide();
52
+
53
+ // clear value
54
+ newBox.find( 'input' ).first().val( '' );
55
+
56
+ // remove add buttons
57
+ $( this ).remove();
58
+ parent.find( '.add-current-ip' ).remove();
59
+
60
+ // add and display new ip box
61
+ parent.after( newBox.show() );
62
+
63
+ parent.parent().find( '.remove-exclude-ip' ).show();
64
+ } );
65
+
66
+ // add current ip
67
+ $( document ).on( 'click', '.add-current-ip', function () {
68
+ // fills input with user's current ip
69
+ $( this ).parent().find( 'input' ).first().val( $( this ).attr( 'data-rel' ) );
70
+ } );
71
+
72
+ // display user roles if needed
73
+ $( document ).on( 'change', '.pvc-chosen-groups', function () {
74
+ var foundRoles = false;
75
+
76
+ // check whether roles are selected
77
+ $( this ).find( ':selected' ).each( function ( i, item ) {
78
+ if ( item.value === 'roles' ) {
79
+ foundRoles = true;
80
+ }
81
+ } );
82
+
83
+ // are roles selected?
84
+ if ( foundRoles ) {
85
+ $( this ).parent().find( '.pvc_user_roles' ).fadeIn( 300 );
86
+ } else {
87
+ $( this ).parent().find( '.pvc_user_roles' ).fadeOut( 300 );
88
+ }
89
+ } );
90
+
91
+ } );
92
+
93
+ } )( jQuery );
js/admin.js DELETED
@@ -1,94 +0,0 @@
1
- jQuery(document).ready(function($) {
2
-
3
- // default chosen
4
- $('.pvc-chosen').chosen({
5
- disable_search_threshold: 8,
6
- display_selected_options: false,
7
- search_contains: true,
8
- width: '300px'
9
- });
10
-
11
-
12
- // time types and position
13
- $('.pvc-chosen-short').chosen({
14
- disable_search_threshold: 8,
15
- width: '200px'
16
- });
17
-
18
-
19
- // ask whether reset options to defaults
20
- $(document).on('click', '.reset_pvc_settings', function() {
21
- return confirm(pvcArgsSettings.resetToDefaults);
22
- });
23
-
24
-
25
- // removes ip box
26
- $(document).on('click', '.remove-exclude-ip', function() {
27
- var parent = $(this).parent(),
28
- nextParent = parent.parent(),
29
- addButton = parent.find('.add-exclude-ip').hide(),
30
- addCurrentIPButton = parent.find('.add-current-ip').hide();
31
-
32
- // removes ip box
33
- parent.remove();
34
-
35
- var children = nextParent.find('div');
36
-
37
- // was there add button?
38
- if(addButton.length === 1) {
39
- children.last().append(addButton.show(), ' ', addCurrentIPButton.show());
40
- // children.last().append();
41
- }
42
-
43
- // only one ip box left?
44
- if(children.length === 1) {
45
- children.find('.remove-exclude-ip').hide();
46
- }
47
- });
48
-
49
-
50
- // adds ip box
51
- $(document).on('click', '.add-exclude-ip', function() {
52
- var parent = $(this).parent(),
53
- newBox = parent.clone().hide();
54
-
55
- // clears value
56
- newBox.find('input').first().val('');
57
-
58
- // removes add buttons
59
- $(this).remove();
60
- parent.find('.add-current-ip').remove();
61
-
62
- // adds and displays new ip box
63
- parent.after(newBox.show());
64
-
65
- parent.parent().find('.remove-exclude-ip').show();
66
- });
67
-
68
-
69
- // adds current ip
70
- $(document).on('click', '.add-current-ip', function() {
71
- // fills input with user's current ip
72
- $(this).parent().find('input').first().val($(this).attr('data-rel'));
73
- });
74
-
75
-
76
- // displays user roles if needed
77
- $(document).on('change', '.pvc-chosen-groups', function() {
78
- var foundRoles = false;
79
-
80
- // checks whether roles are selected
81
- $(this).find(':selected').each(function(i, item) {
82
- if(item.value === 'roles') {
83
- foundRoles = true;
84
- }
85
- });
86
-
87
- // are roles selected?
88
- if(foundRoles) {
89
- $(this).parent().find('.pvc_user_roles').fadeIn(300);
90
- } else {
91
- $(this).parent().find('.pvc_user_roles').fadeOut(300);
92
- }
93
- });
94
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/frontend.js CHANGED
@@ -1,14 +1,14 @@
1
- (function ($) {
2
 
3
- $(document).ready(function () {
4
 
5
- $.post(pvcArgsFrontend.ajaxURL, {
6
- action: 'pvc-check-post',
7
- pvc_nonce: pvcArgsFrontend.nonce,
8
- post_id: pvcArgsFrontend.postID,
9
- post_type: pvcArgsFrontend.postType
10
- });
11
 
12
- });
13
 
14
- })(jQuery);
1
+ ( function ( $ ) {
2
 
3
+ $( document ).ready( function () {
4
 
5
+ $.post( pvcArgsFrontend.ajaxURL, {
6
+ action: 'pvc-check-post',
7
+ pvc_nonce: pvcArgsFrontend.nonce,
8
+ post_id: pvcArgsFrontend.postID,
9
+ post_type: pvcArgsFrontend.postType
10
+ } );
11
 
12
+ } );
13
 
14
+ } )( jQuery );
languages/post-views-counter-hr.mo ADDED
Binary file
languages/post-views-counter-hr.po ADDED
@@ -0,0 +1,579 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Post Views Counter v1.0.7\n"
4
+ "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: \n"
6
+ "PO-Revision-Date: 2015-04-09 17:59+0100\n"
7
+ "Last-Translator: zytzagoo\n"
8
+ "Language-Team: \n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "Plural-Forms: nplurals=3; plural=n%100/10==1 ? 2 : n%10==1 ? 0 : (n+9)%10>3 ? 2 : 1;\n"
13
+ "X-Generator: Poedit 1.7.5\n"
14
+ "X-Poedit-SourceCharset: utf-8\n"
15
+ "X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2\n"
16
+ "X-Poedit-Basepath: ../\n"
17
+ "X-Textdomain-Support: yes\n"
18
+ "Language: hr_HR\n"
19
+ "X-Poedit-SearchPath-0: .\n"
20
+
21
+ # @ post-views-counter
22
+ #: includes/columns.php:45 includes/columns.php:183 includes/columns.php:190
23
+ msgid "Post Views"
24
+ msgstr "Pregledi"
25
+
26
+ # @ post-views-counter
27
+ #: includes/cron.php:51
28
+ msgid "Post Views Counter reset daily counts interval"
29
+ msgstr "Interval resetiranja dnevnih podataka o pregledima"
30
+
31
+ # @ post-views-counter
32
+ #: includes/cron.php:56
33
+ msgid "Post Views Counter cache flush interval"
34
+ msgstr "Interval spremanja broja pregleda iz privremene memorije u WordPress bazu"
35
+
36
+ # @ post-views-counter
37
+ #: includes/functions.php:125
38
+ msgid "No Posts"
39
+ msgstr "Nema rezultata"
40
+
41
+ # @ post-views-counter
42
+ #: includes/settings.php:36
43
+ msgid "Enable"
44
+ msgstr "Uključeno"
45
+
46
+ # @ post-views-counter
47
+ #: includes/settings.php:37
48
+ msgid "Disable"
49
+ msgstr "Isključeno"
50
+
51
+ # @ post-views-counter
52
+ #: includes/settings.php:41
53
+ msgid "PHP"
54
+ msgstr "PHP"
55
+
56
+ # @ post-views-counter
57
+ #: includes/settings.php:42
58
+ msgid "JavaScript"
59
+ msgstr "JavaScript"
60
+
61
+ # @ post-views-counter
62
+ #: includes/settings.php:46
63
+ msgid "minutes"
64
+ msgstr "minuta/minute"
65
+
66
+ # @ post-views-counter
67
+ #: includes/settings.php:47
68
+ msgid "hours"
69
+ msgstr "sat/sata/sati"
70
+
71
+ # @ post-views-counter
72
+ #: includes/settings.php:48
73
+ msgid "days"
74
+ msgstr "dan/dana"
75
+
76
+ # @ post-views-counter
77
+ #: includes/settings.php:49
78
+ msgid "weeks"
79
+ msgstr "tjedan/tjedana/tjedna"
80
+
81
+ # @ post-views-counter
82
+ #: includes/settings.php:50
83
+ msgid "months"
84
+ msgstr "mjesec/mjeseca/mjeseci"
85
+
86
+ # @ post-views-counter
87
+ #: includes/settings.php:51
88
+ msgid "years"
89
+ msgstr "godinu/godine/godina"
90
+
91
+ # @ post-views-counter
92
+ #: includes/settings.php:55
93
+ msgid "robots"
94
+ msgstr "roboti"
95
+
96
+ # @ post-views-counter
97
+ #: includes/settings.php:56
98
+ msgid "logged in users"
99
+ msgstr "prijavljeni korisnici"
100
+
101
+ # @ post-views-counter
102
+ #: includes/settings.php:57
103
+ msgid "guests"
104
+ msgstr "gosti"
105
+
106
+ # @ post-views-counter
107
+ #: includes/settings.php:58
108
+ msgid "selected user roles"
109
+ msgstr "odabrane korisničke role"
110
+
111
+ # @ post-views-counter
112
+ #: includes/settings.php:62
113
+ msgid "before the content"
114
+ msgstr "prije sadržaja"
115
+
116
+ # @ post-views-counter
117
+ #: includes/settings.php:63
118
+ msgid "after the content"
119
+ msgstr "nakon sadržaja"
120
+
121
+ # @ post-views-counter
122
+ #: includes/settings.php:64
123
+ msgid "manual"
124
+ msgstr "ručno"
125
+
126
+ # @ post-views-counter
127
+ #: includes/settings.php:68
128
+ msgid "icon"
129
+ msgstr "ikona"
130
+
131
+ # @ post-views-counter
132
+ #: includes/settings.php:69
133
+ msgid "label"
134
+ msgstr "oznaka"
135
+
136
+ # @ post-views-counter
137
+ #: includes/settings.php:74
138
+ msgid "General"
139
+ msgstr "Općenito"
140
+
141
+ # @ post-views-counter
142
+ #: includes/settings.php:80
143
+ msgid "Display"
144
+ msgstr "Prikaz"
145
+
146
+ # @ post-views-counter
147
+ #. translators: plugin header field 'Name'
148
+ #: includes/settings.php:135 includes/settings.php:136
149
+ #: includes/settings.php:151 includes/settings.php:163
150
+ #: post-views-counter.php:0
151
+ msgid "Post Views Counter"
152
+ msgstr "Brojač pregleda"
153
+
154
+ # @ post-views-counter
155
+ #: includes/settings.php:165
156
+ msgid "Need support?"
157
+ msgstr "Trebate pomoć?"
158
+
159
+ # @ post-views-counter
160
+ #: includes/settings.php:166
161
+ msgid "If you are having problems with this plugin, please talk about them in the"
162
+ msgstr "Ako imate poteškoća s korištenjem ovog dodatka uključite se u raspravu na"
163
+
164
+ # @ post-views-counter
165
+ #: includes/settings.php:166
166
+ msgid "Support forum"
167
+ msgstr "forumima podrške"
168
+
169
+ # @ post-views-counter
170
+ #: includes/settings.php:168
171
+ msgid "Do you like this plugin?"
172
+ msgstr "Zadovoljni ste s ovim dodatkom?"
173
+
174
+ # @ post-views-counter
175
+ #: includes/settings.php:169
176
+ msgid "Rate it 5"
177
+ msgstr "Ocjenite ga 5-icom"
178
+
179
+ # @ post-views-counter
180
+ #: includes/settings.php:169
181
+ msgid "on WordPress.org"
182
+ msgstr "na WordPress.org"
183
+
184
+ # @ post-views-counter
185
+ #: includes/settings.php:170
186
+ msgid "Blog about it & link to the"
187
+ msgstr "Pišite o njemu i linkajte ga na"
188
+
189
+ # @ post-views-counter
190
+ #: includes/settings.php:170
191
+ msgid "plugin page"
192
+ msgstr "stranicu dodatka"
193
+
194
+ # @ post-views-counter
195
+ #: includes/settings.php:171
196
+ msgid "Check out our other"
197
+ msgstr "Provjerite naše ostale"
198
+
199
+ # @ post-views-counter
200
+ #: includes/settings.php:171
201
+ msgid "WordPress plugins"
202
+ msgstr "WordPress dodatke"
203
+
204
+ # @ post-views-counter
205
+ #: includes/settings.php:174
206
+ msgid "Created by"
207
+ msgstr "Autor"
208
+
209
+ # @ post-views-counter
210
+ #: includes/settings.php:190
211
+ msgid "Reset to defaults"
212
+ msgstr "Vrati na zadane postavke"
213
+
214
+ # @ post-views-counter
215
+ #: includes/settings.php:207
216
+ msgid "General settings"
217
+ msgstr "Općenite postavke"
218
+
219
+ # @ post-views-counter
220
+ #: includes/settings.php:208
221
+ msgid "Post Types Count"
222
+ msgstr "Vrste objava koje se broje"
223
+
224
+ # @ post-views-counter
225
+ #: includes/settings.php:209
226
+ msgid "Counter Mode"
227
+ msgstr "Način rada brojača"
228
+
229
+ # @ post-views-counter
230
+ #: includes/settings.php:210
231
+ msgid "Post Views Column"
232
+ msgstr "Pregledi stupac"
233
+
234
+ # @ post-views-counter
235
+ #: includes/settings.php:211
236
+ msgid "Time Between Counts"
237
+ msgstr "Vrijeme između posjeta"
238
+
239
+ # @ post-views-counter
240
+ #: includes/settings.php:214
241
+ msgid "Exclude Visitors"
242
+ msgstr "Isključi posjete"
243
+
244
+ # @ post-views-counter
245
+ #: includes/settings.php:215
246
+ msgid "Exclude IPs"
247
+ msgstr "Isključi IP adrese"
248
+
249
+ # @ post-views-counter
250
+ #: includes/settings.php:216
251
+ msgid "WP-PostViews"
252
+ msgstr "WP-PostViews"
253
+
254
+ # @ post-views-counter
255
+ #: includes/settings.php:217
256
+ msgid "Deactivation"
257
+ msgstr "Deaktivacija"
258
+
259
+ # @ post-views-counter
260
+ #: includes/settings.php:221
261
+ msgid "Display settings"
262
+ msgstr "Postavke prikaza"
263
+
264
+ # @ post-views-counter
265
+ #: includes/settings.php:222
266
+ msgid "Post Views Label"
267
+ msgstr "Oznaka brojača"
268
+
269
+ # @ post-views-counter
270
+ #: includes/settings.php:223
271
+ msgid "Post Types Display"
272
+ msgstr "Vrste objava uz koje se prikazuje brojač"
273
+
274
+ # @ post-views-counter
275
+ #: includes/settings.php:224
276
+ msgid "Restrict Display"
277
+ msgstr "Ograničenje prikaza"
278
+
279
+ # @ post-views-counter
280
+ #: includes/settings.php:225
281
+ msgid "Position"
282
+ msgstr "Pozicija brojača"
283
+
284
+ # @ post-views-counter
285
+ #: includes/settings.php:226
286
+ msgid "Display Style"
287
+ msgstr "Stil prikaza"
288
+
289
+ # @ post-views-counter
290
+ #: includes/settings.php:227
291
+ msgid "Icon Class"
292
+ msgstr "CSS klasa ikone"
293
+
294
+ # @ post-views-counter
295
+ #: includes/settings.php:240
296
+ msgid "Enter the label for the post views counter field."
297
+ msgstr "Upišite naziv/oznaku koja će se prikazivati prije vrijednosti brojača"
298
+
299
+ # @ post-views-counter
300
+ #: includes/settings.php:253
301
+ msgid "Select post types"
302
+ msgstr "Odaberite vrste objava"
303
+
304
+ # @ post-views-counter
305
+ #: includes/settings.php:263
306
+ msgid "Select post types for which post views will be counted."
307
+ msgstr "Odaberite vrste objava za koje će se brojati posjete."
308
+
309
+ # @ post-views-counter
310
+ #: includes/settings.php:276 includes/settings.php:412
311
+ #: includes/settings.php:569
312
+ msgid "Select groups"
313
+ msgstr "Odaberite grupe"
314
+
315
+ # @ post-views-counter
316
+ #: includes/settings.php:286
317
+ msgid "Select post types for which post views will be displayed."
318
+ msgstr "Odaberite vrste objava na kojima će se prikazivati brojač posjeta."
319
+
320
+ # @ post-views-counter
321
+ #: includes/settings.php:308
322
+ msgid "Select the method of collecting post views data. If you are using any of the caching plugins select Javascript."
323
+ msgstr "Odaberite način rada brojača. Koristite li neki od dodataka za poboljšanje performansi putem spremanja podataka u privremenu memoriju (ili slično), odaberite JavaScript."
324
+
325
+ # @ post-views-counter
326
+ #: includes/settings.php:330
327
+ msgid "Enable to display post views count column for each of the selected post types."
328
+ msgstr "Uključite ako želite prikaz stupca s vrijednostima brojača za odabrane vrste objava u administraciji."
329
+
330
+ # @ post-views-counter
331
+ #: includes/settings.php:353
332
+ msgid "Enter the time between single user visit count."
333
+ msgstr "Upišite vrijeme koje mora proći između dvije posjete istog korisnika kako bi se brojač povećao."
334
+
335
+ # @ post-views-counter
336
+ #: includes/settings.php:377
337
+ msgid "Delete single day post views data older than specified above. Enter 0 (number zero) if you want to preserve your data regardless of its age."
338
+ msgstr "Automatsko brisanje podataka o dnevnim pregledima starijim od navedenog vremena. Upišite 0 (brojka nula) ako želite čuvati sve dnevne podatke bez obzira na starost."
339
+
340
+ # @ post-views-counter
341
+ #: includes/settings.php:423 includes/settings.php:584
342
+ msgid "Select user roles"
343
+ msgstr "Odaberite korisničke uloge"
344
+
345
+ # @ post-views-counter
346
+ #: includes/settings.php:434
347
+ msgid "Select the type of visitors to be excluded from post views count."
348
+ msgstr "Odaberite vrste posjeta koje ne želite brojati."
349
+
350
+ # @ post-views-counter
351
+ #: includes/settings.php:450 includes/settings.php:459
352
+ msgid "Remove"
353
+ msgstr "Ukloni"
354
+
355
+ # @ post-views-counter
356
+ #: includes/settings.php:459
357
+ msgid "Add new"
358
+ msgstr "Dodaj"
359
+
360
+ # @ post-views-counter
361
+ #: includes/settings.php:459
362
+ msgid "Add my current IP"
363
+ msgstr "Dodaj moju trenutnu IP adresu"
364
+
365
+ # @ post-views-counter
366
+ #: includes/settings.php:461
367
+ msgid "Enter the IP addresses to be excluded from post views count."
368
+ msgstr "Upišite IP adrese s kojih se posjete neće brojati."
369
+
370
+ # @ post-views-counter
371
+ #: includes/settings.php:473
372
+ msgid "Import"
373
+ msgstr "Uvoz"
374
+
375
+ # @ post-views-counter
376
+ #: includes/settings.php:475
377
+ msgid "Import post views data from WP-PostViews plugin."
378
+ msgstr "Uvezi podatke o brojačima iz WP-PostViews dodatka."
379
+
380
+ # @ post-views-counter
381
+ #: includes/settings.php:476
382
+ msgid "Override existing Post Views Counter data."
383
+ msgstr "Uredi postojeće podatke prilikom unosa."
384
+
385
+ # @ post-views-counter
386
+ #: includes/settings.php:498
387
+ msgid "Enable to delete all plugin data on deactivation."
388
+ msgstr "\"Uključeno\" znači da će se prilikom deaktivacije dodatka svi podaci nepovratno obrisati."
389
+
390
+ # @ post-views-counter
391
+ #: includes/settings.php:520
392
+ msgid "Select where would you like to display the post views counter. Use [post-views] shortcode for manual display."
393
+ msgstr "Odaberite gdje želite prikazati brojač. Možete koristiti [post-views] shortcode za ručno prikazivanje negdje u temi."
394
+
395
+ # @ post-views-counter
396
+ #: includes/settings.php:542
397
+ msgid "Choose how to display the post views counter."
398
+ msgstr "Odaberite kako želite prikazati brojač."
399
+
400
+ # @ post-views-counter
401
+ #: includes/settings.php:556
402
+ #, php-format
403
+ msgid "Enter the post views icon class. Any of the <a href=\"%s\" target=\"_blank\">Dashicons</a> classes are available."
404
+ msgstr "Upišite CSS klasu ikone brojača (bilo koju od standardnih <a href=\"%s\" target=\"_blank\">Dashicons</a> klasa)."
405
+
406
+ # @ post-views-counter
407
+ #: includes/settings.php:595
408
+ msgid "Use it to hide the post views counter from selected type of visitors."
409
+ msgstr "Brojač pregleda neće se prikazivati ovim vrstama posjetitelja (biti će skriven)."
410
+
411
+ # @ post-views-counter
412
+ #: includes/settings.php:626
413
+ msgid "WP-PostViews data imported succesfully."
414
+ msgstr "WP-PostViews podaci uspješno uvezeni."
415
+
416
+ # @ post-views-counter
417
+ #: includes/settings.php:628
418
+ msgid "There was no data to import."
419
+ msgstr "Nisu pronađeni podaci za uvoz."
420
+
421
+ # @ post-views-counter
422
+ #: includes/settings.php:786
423
+ msgid "General settings restored to defaults."
424
+ msgstr "Općenite postavke vraćene su na zadane vrijednosti."
425
+
426
+ # @ post-views-counter
427
+ #: includes/settings.php:790
428
+ msgid "Display settings restored to defaults."
429
+ msgstr "Postavke prikaza vraćene su na zadane vrijednosti."
430
+
431
+ # @ post-views-counter
432
+ #: includes/settings.php:810
433
+ msgid "Support"
434
+ msgstr "Podrška"
435
+
436
+ # @ post-views-counter
437
+ #: includes/widgets.php:32 includes/widgets.php:43
438
+ msgid "Most Viewed Posts"
439
+ msgstr "Najčitanije objave"
440
+
441
+ # @ post-views-counter
442
+ #: includes/widgets.php:34
443
+ msgid "Displays a list of the most viewed posts"
444
+ msgstr "Prikazuje listu najčitanijih objava"
445
+
446
+ # @ post-views-counter
447
+ #: includes/widgets.php:51
448
+ msgid "No Posts found"
449
+ msgstr "Nema rezultata"
450
+
451
+ # @ post-views-counter
452
+ #: includes/widgets.php:55
453
+ msgid "Ascending"
454
+ msgstr "Rastući (A-Z)"
455
+
456
+ # @ post-views-counter
457
+ #: includes/widgets.php:56
458
+ msgid "Descending"
459
+ msgstr "Padajući (Z-A)"
460
+
461
+ # @ post-views-counter
462
+ #: includes/widgets.php:93
463
+ msgid "Title"
464
+ msgstr "Naslov"
465
+
466
+ # @ post-views-counter
467
+ #: includes/widgets.php:110
468
+ msgid "Number of posts to show"
469
+ msgstr "Broj objava koje želite prikazati"
470
+
471
+ # @ post-views-counter
472
+ #: includes/widgets.php:114
473
+ msgid "No posts message"
474
+ msgstr "Nema objava"
475
+
476
+ # @ post-views-counter
477
+ #: includes/widgets.php:118
478
+ msgid "Order"
479
+ msgstr "Poredak"
480
+
481
+ # @ post-views-counter
482
+ #: includes/widgets.php:130
483
+ msgid "Display post views?"
484
+ msgstr "Prikaži brojač?"
485
+
486
+ # @ post-views-counter
487
+ #: includes/widgets.php:132
488
+ msgid "Display post excerpt?"
489
+ msgstr "Prikaži sažetak objave?"
490
+
491
+ # @ post-views-counter
492
+ #: includes/widgets.php:134
493
+ msgid "Display post thumbnail?"
494
+ msgstr "Prikaži thumbnail objave?"
495
+
496
+ # @ post-views-counter
497
+ #: includes/widgets.php:137
498
+ msgid "Thumbnail size"
499
+ msgstr "Dimenzije thumbnaila"
500
+
501
+ # @ post-views-counter
502
+ #. translators: plugin header field 'PluginURI'
503
+ #: post-views-counter.php:0
504
+ msgid "http://www.dfactory.eu/plugins/post-views-counter/"
505
+ msgstr "http://www.dfactory.eu/plugins/post-views-counter/"
506
+
507
+ # @ post-views-counter
508
+ #. translators: plugin header field 'Description'
509
+ #: post-views-counter.php:0
510
+ msgid "Forget WP-PostViews. Display how many times a post, page or custom post type had been viewed in a simple, fast and reliable way."
511
+ msgstr "Zaboravite WP-PostViews. Prikažite broj pregleda pojedine objave, stranice ili bilo kojih drugih vrsta objava na jednostavan, brz i pouzdan način."
512
+
513
+ # @ post-views-counter
514
+ #. translators: plugin header field 'Author'
515
+ #: post-views-counter.php:0
516
+ msgid "dFactory"
517
+ msgstr "dFactory"
518
+
519
+ # @ post-views-counter
520
+ #. translators: plugin header field 'AuthorURI'
521
+ #: post-views-counter.php:0
522
+ msgid "http://www.dfactory.eu/"
523
+ msgstr "http://www.dfactory.eu/"
524
+
525
+ # @ post-views-counter
526
+ #: post-views-counter.php:297
527
+ msgid "Are you sure you want to reset these settings to defaults?"
528
+ msgstr "Jeste li sigurni da želite vratiti postavke na njihove zadane vrijednosti?"
529
+
530
+ # @ post-views-counter
531
+ #: post-views-counter.php:330
532
+ msgid "Settings"
533
+ msgstr "Postavke"
534
+
535
+ # @ post-views-counter
536
+ #: includes/columns.php:49
537
+ msgid "Edit"
538
+ msgstr "Uredi"
539
+
540
+ # @ post-views-counter
541
+ #: includes/columns.php:53
542
+ msgid "Adjust the views count for this post."
543
+ msgstr "Promijeni vrijednost broja pregleda ove objave"
544
+
545
+ # @ post-views-counter
546
+ #: includes/columns.php:57
547
+ msgid "OK"
548
+ msgstr "OK"
549
+
550
+ # @ post-views-counter
551
+ #: includes/columns.php:58
552
+ msgid "Cancel"
553
+ msgstr "Odustani"
554
+
555
+ # @ post-views-counter
556
+ #: includes/settings.php:212
557
+ msgid "Reset Data Interval"
558
+ msgstr "Interval resetiranja podataka brojača"
559
+
560
+ # @ post-views-counter
561
+ #: includes/settings.php:213
562
+ msgid "Flush Object Cache Interval"
563
+ msgstr "Interval spremanja privremene memorije"
564
+
565
+ # @ post-views-counter
566
+ #: includes/settings.php:400
567
+ msgid "How often to flush cached view counts from the object cache into the database. This feature is used only if a persistent object cache is detected and the interval is greater than 0 (number zero)). When used, view counts will be collected and stored in the object cache instead of the database and will then be asynchronously flushed to the database according to the specified interval.<br /><strong>Notice:</strong> Potential data loss may occur if the object cache is cleared/unavailable for the duration of the interval."
568
+ msgstr "Koliko često se podaci iz privremene memorije trajno pohranjuju u bazu. Ova mogućnost biti će upotrebljena samo ako je podržana i ako je vrijednost intervala veća od 0 (brojka nula). Tada će se podaci o posjetama spremati u privremenu memoriju umjesto direktno u bazu (čime se dobija na performansama) i tek periodički trajno pohranjivati u bazu. <br><strong>Napomena:</strong> Ako se privremena memorija iznenada očisti i/ili je nedostupna, podaci iz privremene memorije mogu biti bespovratno izgubljeni."
569
+
570
+ # @ post-views-counter
571
+ #: includes/widgets.php:97
572
+ msgid "Post Types"
573
+ msgstr "Vrste objava"
574
+
575
+ # @ post-views-counter
576
+ #. translators: plugin header field 'Version'
577
+ #: post-views-counter.php:0
578
+ msgid "1.0.7"
579
+ msgstr "1.0.7"
post-views-counter.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Post Views Counter
4
  Description: Forget WP-PostViews. Display how many times a post, page or custom post type had been viewed in a simple, fast and reliable way.
5
- Version: 1.0.7
6
  Author: dFactory
7
  Author URI: http://www.dfactory.eu/
8
  Plugin URI: http://www.dfactory.eu/plugins/post-views-counter/
@@ -21,121 +21,125 @@ The above copyright notice and this permission notice shall be included in all c
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')) exit;
 
26
 
27
- define('POST_VIEWS_COUNTER_URL', plugins_url('', __FILE__));
28
- define('POST_VIEWS_COUNTER_PATH', plugin_dir_path(__FILE__));
29
- define('POST_VIEWS_COUNTER_REL_PATH', dirname(plugin_basename(__FILE__)).'/');
30
 
31
- include_once(POST_VIEWS_COUNTER_PATH.'includes/update.php');
32
- include_once(POST_VIEWS_COUNTER_PATH.'includes/settings.php');
33
- include_once(POST_VIEWS_COUNTER_PATH.'includes/query.php');
34
- include_once(POST_VIEWS_COUNTER_PATH.'includes/cron.php');
35
- include_once(POST_VIEWS_COUNTER_PATH.'includes/counter.php');
36
- include_once(POST_VIEWS_COUNTER_PATH.'includes/columns.php');
37
- include_once(POST_VIEWS_COUNTER_PATH.'includes/frontend.php');
38
- include_once(POST_VIEWS_COUNTER_PATH.'includes/widgets.php');
39
 
40
  /**
41
  * Post Views Counter class
42
  *
43
  * @class Post_Views_Counter
44
- * @version 1.0.7
45
  */
46
  class Post_Views_Counter {
 
47
  private static $_instance;
48
  private $instances;
49
  private $options;
50
  private $defaults = array(
51
- 'general' => array(
52
- 'post_types_count' => array('post'),
53
- 'counter_mode' => 'php',
54
- 'post_views_column' => true,
55
- 'time_between_counts' => array(
56
  'number' => 24,
57
- 'type' => 'hours'
58
  ),
59
- 'reset_counts' => array(
60
  'number' => 30,
61
- 'type' => 'days'
62
  ),
63
- 'flush_interval' => array(
64
  'number' => 0,
65
- 'type' => 'minutes'
66
  ),
67
- 'exclude' => array(
68
  'groups' => array(),
69
- 'roles' => array()
70
  ),
71
- 'exclude_ips' => array(),
72
- 'deactivation_delete' => false,
73
- 'cron_run' => true,
74
- 'cron_update' => true
75
  ),
76
- 'display' => array(
77
- 'label' => 'Post Views:',
78
- 'post_types_display' => array('post'),
79
- 'restrict_display' => array(
80
  'groups' => array(),
81
- 'roles' => array()
82
  ),
83
- 'position' => 'after',
84
- 'display_style' => array(
85
- 'icon' => true,
86
- 'text' => true
87
  ),
88
- 'link_to_post' => true,
89
- 'icon_class' => 'dashicons-visibility'
90
  ),
91
- 'version' => '1.0.7'
92
  );
93
 
94
-
95
  public static function instance() {
96
- if(self::$_instance === null)
97
  self::$_instance = new self();
98
 
99
  return self::$_instance;
100
  }
101
 
 
 
 
102
 
103
- private function __clone() {}
104
- private function __wakeup() {}
105
-
106
 
107
  private function __construct() {
108
- register_activation_hook(__FILE__, array(&$this, 'activation'));
109
- register_deactivation_hook(__FILE__, array(&$this, 'deactivation'));
110
 
111
  // settings
112
  $this->options = array(
113
- 'general' => array_merge($this->defaults['general'], get_option('post_views_counter_settings_general', $this->defaults['general'])),
114
- 'display' => array_merge($this->defaults['display'], get_option('post_views_counter_settings_display', $this->defaults['display']))
115
  );
116
 
117
  // actions
118
- add_action('plugins_loaded', array(&$this, 'load_textdomain'));
119
- add_action('admin_enqueue_scripts', array(&$this, 'admin_scripts_styles'));
120
- add_action('wp_loaded', array(&$this, 'load_pluggable_functions'), 10);
121
 
122
  // filters
123
- add_filter('plugin_action_links', array(&$this, 'plugin_settings_link'), 10, 2);
 
124
  }
125
 
126
-
127
  /**
128
  * Execution of plugin activation function
129
- */
130
  public function activation() {
131
  global $wpdb, $charset_collate;
132
 
133
  // required for dbdelta
134
- require_once(ABSPATH.'wp-admin/includes/upgrade.php');
135
 
136
  // create post views table
137
- dbDelta('
138
- CREATE TABLE IF NOT EXISTS '.$wpdb->prefix.'post_views (
139
  id bigint unsigned NOT NULL,
140
  type tinyint(1) unsigned NOT NULL,
141
  period varchar(8) NOT NULL,
@@ -143,32 +147,31 @@ class Post_Views_Counter {
143
  PRIMARY KEY (type, period, id),
144
  UNIQUE INDEX id_period (id, period) USING BTREE,
145
  INDEX type_period_count (type, period, count) USING BTREE
146
- ) '.$charset_collate.';'
147
  );
148
 
149
  // add default options
150
- add_option('post_views_counter_settings_general', $this->defaults['general'], '', 'no');
151
- add_option('post_views_counter_settings_display', $this->defaults['display'], '', 'no');
152
- add_option('post_views_counter_version', $this->defaults['version'], '', 'no');
153
 
154
  // schedule cache flush
155
  $this->schedule_cache_flush();
156
  }
157
 
158
-
159
  /**
160
  * Execution of plugin deactivation function
161
- */
162
  public function deactivation() {
163
  // delete default options
164
- if ($this->options['general']['deactivation_delete']) {
165
- delete_option('post_views_counter_settings_general');
166
- delete_option('post_views_counter_settings_display');
167
  }
168
 
169
  // remove schedule
170
- wp_clear_scheduled_hook('pvc_reset_counts');
171
- remove_action('pvc_reset_counts', array(Post_Views_Counter()->get_instance('cron'), 'reset_counts'));
172
 
173
  $this->remove_cache_flush();
174
  }
@@ -176,7 +179,7 @@ class Post_Views_Counter {
176
  /**
177
  * Schedule cache flushing if it's not already scheduled
178
  */
179
- public function schedule_cache_flush($forced = true) {
180
  if ( $forced || ! wp_next_scheduled( 'pvc_flush_cached_counts' ) ) {
181
  wp_schedule_event( time(), 'post_views_counter_flush_interval', 'pvc_flush_cached_counts' );
182
  }
@@ -187,153 +190,152 @@ class Post_Views_Counter {
187
  */
188
  public function remove_cache_flush() {
189
  wp_clear_scheduled_hook( 'pvc_flush_cached_counts' );
190
- remove_action( 'pvc_flush_cached_counts', array( Post_Views_Counter()->get_instance('cron'), 'flush_cached_counts' ) );
191
  }
192
 
193
-
194
  /**
195
  * Load text domain
196
- */
197
  public function load_textdomain() {
198
- load_plugin_textdomain('post-views-counter', false, POST_VIEWS_COUNTER_REL_PATH.'languages/');
199
  }
200
 
201
-
202
  /**
203
  * Load pluggable template functions
204
- */
205
  public function load_pluggable_functions() {
206
- include_once(POST_VIEWS_COUNTER_PATH.'includes/functions.php');
207
  }
208
 
209
-
210
  /**
211
  * Set instance of class
212
- */
213
- public function add_instance($name, $instance) {
214
  $this->instances[$name] = $instance;
215
  }
216
 
217
-
218
  /**
219
  * Get instance of a class
220
- */
221
- public function get_instance($name) {
222
- if(in_array($name, array('counter', 'settings'), true))
223
  return $this->instances[$name];
224
  }
225
 
226
-
227
  /**
228
  * Get allowed attribute
229
- */
230
- public function get_attribute($attribute) {
231
- if (in_array($attribute, array('options', 'defaults'), true)) {
232
- switch(func_num_args()) {
233
  case 1:
234
  return $this->{$attribute};
235
 
236
  case 2:
237
- return $this->{$attribute}[func_get_arg(1)];
238
 
239
  case 3:
240
- return $this->{$attribute}[func_get_arg(1)][func_get_arg(2)];
241
 
242
  case 4:
243
- return $this->{$attribute}[func_get_arg(1)][func_get_arg(2)][func_get_arg(3)];
244
  }
245
- }
246
- else
247
  return false;
248
  }
249
 
250
-
251
  /**
252
  * Enqueue admin scripts and styles
253
- */
254
- public function admin_scripts_styles($page) {
255
-
256
  wp_register_style(
257
- 'pvc-admin',
258
- POST_VIEWS_COUNTER_URL.'/css/admin.css'
259
  );
260
 
261
  wp_register_style(
262
- 'pvc-chosen',
263
- POST_VIEWS_COUNTER_URL.'/assets/chosen/chosen.min.css'
264
  );
265
-
266
  wp_register_script(
267
- 'pvc-admin-chosen',
268
- POST_VIEWS_COUNTER_URL.'/assets/chosen/chosen.jquery.min.js',
269
- array('jquery'),
270
- $this->defaults['version']
271
  );
272
 
273
  wp_register_script(
274
- 'pvc-admin-settings',
275
- POST_VIEWS_COUNTER_URL.'/js/admin-settings.js',
276
- array('jquery', 'pvc-admin-chosen'),
277
- $this->defaults['version']
278
  );
279
-
280
  wp_register_script(
281
- 'pvc-admin-post',
282
- POST_VIEWS_COUNTER_URL.'/js/admin-post.js',
283
- array('jquery'),
284
- $this->defaults['version']
285
  );
286
-
287
  // load on PVC settings page
288
- if ($page === 'settings_page_post-views-counter') {
289
-
290
- wp_enqueue_script('pvc-admin-chosen');
291
- wp_enqueue_script('pvc-admin-settings');
292
 
293
  wp_localize_script(
294
- 'pvc-admin-settings',
295
- 'pvcArgsSettings',
296
- array(
297
- 'resetToDefaults' => __('Are you sure you want to reset these settings to defaults?', 'post-views-counter')
298
  )
299
  );
300
 
301
- wp_enqueue_style('pvc-chosen');
302
- wp_enqueue_style('pvc-admin');
303
-
304
- // load on single post page
305
- } elseif ($page = 'post.php') {
306
-
307
- $post_types = Post_Views_Counter()->get_attribute('options', 'general', 'post_types_count');
308
-
309
- if (!in_array(get_post_type(), (array)$post_types))
310
  return;
311
-
312
- wp_enqueue_style('pvc-admin');
313
- wp_enqueue_script('pvc-admin-post');
314
  }
315
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
316
 
 
 
317
 
318
  /**
319
  * Add link to settings page
320
- */
321
- public function plugin_settings_link($links, $file) {
322
- if (!is_admin() || !current_user_can('manage_options'))
323
  return $links;
324
 
325
  static $plugin;
326
 
327
- $plugin = plugin_basename(__FILE__);
328
 
329
- if ($file == $plugin) {
330
- $settings_link = sprintf('<a href="%s">%s</a>', admin_url('options-general.php').'?page=post-views-counter', __('Settings', 'post-views-counter'));
331
 
332
- array_unshift($links, $settings_link);
333
  }
334
 
335
  return $links;
336
  }
 
337
  }
338
 
339
  /**
@@ -342,12 +344,11 @@ class Post_Views_Counter {
342
  function Post_Views_Counter() {
343
  static $instance;
344
 
345
- // first call to instance() initializes the plugin
346
- if ($instance === null || !($instance instanceof Post_Views_Counter))
347
- $instance = Post_Views_Counter::instance();
348
 
349
- return $instance;
350
  }
351
 
352
- Post_Views_Counter();
353
- ?>
2
  /*
3
  Plugin Name: Post Views Counter
4
  Description: Forget WP-PostViews. Display how many times a post, page or custom post type had been viewed in a simple, fast and reliable way.
5
+ Version: 1.0.8
6
  Author: dFactory
7
  Author URI: http://www.dfactory.eu/
8
  Plugin URI: http://www.dfactory.eu/plugins/post-views-counter/
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
+ define( 'POST_VIEWS_COUNTER_URL', plugins_url( '', __FILE__ ) );
29
+ define( 'POST_VIEWS_COUNTER_PATH', plugin_dir_path( __FILE__ ) );
30
+ define( 'POST_VIEWS_COUNTER_REL_PATH', dirname( plugin_basename( __FILE__ ) ) . '/' );
31
 
32
+ include_once( POST_VIEWS_COUNTER_PATH . 'includes/update.php' );
33
+ include_once( POST_VIEWS_COUNTER_PATH . 'includes/settings.php' );
34
+ include_once( POST_VIEWS_COUNTER_PATH . 'includes/query.php' );
35
+ include_once( POST_VIEWS_COUNTER_PATH . 'includes/cron.php' );
36
+ include_once( POST_VIEWS_COUNTER_PATH . 'includes/counter.php' );
37
+ include_once( POST_VIEWS_COUNTER_PATH . 'includes/columns.php' );
38
+ include_once( POST_VIEWS_COUNTER_PATH . 'includes/frontend.php' );
39
+ include_once( POST_VIEWS_COUNTER_PATH . 'includes/widgets.php' );
40
 
41
  /**
42
  * Post Views Counter class
43
  *
44
  * @class Post_Views_Counter
45
+ * @version 1.0.8
46
  */
47
  class Post_Views_Counter {
48
+
49
  private static $_instance;
50
  private $instances;
51
  private $options;
52
  private $defaults = array(
53
+ 'general' => array(
54
+ 'post_types_count' => array( 'post' ),
55
+ 'counter_mode' => 'php',
56
+ 'post_views_column' => true,
57
+ 'time_between_counts' => array(
58
  'number' => 24,
59
+ 'type' => 'hours'
60
  ),
61
+ 'reset_counts' => array(
62
  'number' => 30,
63
+ 'type' => 'days'
64
  ),
65
+ 'flush_interval' => array(
66
  'number' => 0,
67
+ 'type' => 'minutes'
68
  ),
69
+ 'exclude' => array(
70
  'groups' => array(),
71
+ 'roles' => array()
72
  ),
73
+ 'exclude_ips' => array(),
74
+ 'deactivation_delete' => false,
75
+ 'cron_run' => true,
76
+ 'cron_update' => true
77
  ),
78
+ 'display' => array(
79
+ 'label' => 'Post Views:',
80
+ 'post_types_display' => array( 'post' ),
81
+ 'restrict_display' => array(
82
  'groups' => array(),
83
+ 'roles' => array()
84
  ),
85
+ 'position' => 'after',
86
+ 'display_style' => array(
87
+ 'icon' => true,
88
+ 'text' => true
89
  ),
90
+ 'link_to_post' => true,
91
+ 'icon_class' => 'dashicons-visibility'
92
  ),
93
+ 'version' => '1.0.8'
94
  );
95
 
 
96
  public static function instance() {
97
+ if ( self::$_instance === null )
98
  self::$_instance = new self();
99
 
100
  return self::$_instance;
101
  }
102
 
103
+ private function __clone() {
104
+
105
+ }
106
 
107
+ private function __wakeup() {
108
+
109
+ }
110
 
111
  private function __construct() {
112
+ register_activation_hook( __FILE__, array( &$this, 'activation' ) );
113
+ register_deactivation_hook( __FILE__, array( &$this, 'deactivation' ) );
114
 
115
  // settings
116
  $this->options = array(
117
+ 'general' => array_merge( $this->defaults['general'], get_option( 'post_views_counter_settings_general', $this->defaults['general'] ) ),
118
+ 'display' => array_merge( $this->defaults['display'], get_option( 'post_views_counter_settings_display', $this->defaults['display'] ) )
119
  );
120
 
121
  // actions
122
+ add_action( 'plugins_loaded', array( &$this, 'load_textdomain' ) );
123
+ add_action( 'admin_enqueue_scripts', array( &$this, 'admin_scripts_styles' ) );
124
+ add_action( 'wp_loaded', array( &$this, 'load_pluggable_functions' ), 10 );
125
 
126
  // filters
127
+ add_filter( 'plugin_row_meta', array( &$this, 'plugin_extend_links' ), 10, 2 );
128
+ add_filter( 'plugin_action_links', array( &$this, 'plugin_settings_link' ), 10, 2 );
129
  }
130
 
 
131
  /**
132
  * Execution of plugin activation function
133
+ */
134
  public function activation() {
135
  global $wpdb, $charset_collate;
136
 
137
  // required for dbdelta
138
+ require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
139
 
140
  // create post views table
141
+ dbDelta( '
142
+ CREATE TABLE IF NOT EXISTS ' . $wpdb->prefix . 'post_views (
143
  id bigint unsigned NOT NULL,
144
  type tinyint(1) unsigned NOT NULL,
145
  period varchar(8) NOT NULL,
147
  PRIMARY KEY (type, period, id),
148
  UNIQUE INDEX id_period (id, period) USING BTREE,
149
  INDEX type_period_count (type, period, count) USING BTREE
150
+ ) ' . $charset_collate . ';'
151
  );
152
 
153
  // add default options
154
+ add_option( 'post_views_counter_settings_general', $this->defaults['general'], '', 'no' );
155
+ add_option( 'post_views_counter_settings_display', $this->defaults['display'], '', 'no' );
156
+ add_option( 'post_views_counter_version', $this->defaults['version'], '', 'no' );
157
 
158
  // schedule cache flush
159
  $this->schedule_cache_flush();
160
  }
161
 
 
162
  /**
163
  * Execution of plugin deactivation function
164
+ */
165
  public function deactivation() {
166
  // delete default options
167
+ if ( $this->options['general']['deactivation_delete'] ) {
168
+ delete_option( 'post_views_counter_settings_general' );
169
+ delete_option( 'post_views_counter_settings_display' );
170
  }
171
 
172
  // remove schedule
173
+ wp_clear_scheduled_hook( 'pvc_reset_counts' );
174
+ remove_action( 'pvc_reset_counts', array( Post_Views_Counter()->get_instance( 'cron' ), 'reset_counts' ) );
175
 
176
  $this->remove_cache_flush();
177
  }
179
  /**
180
  * Schedule cache flushing if it's not already scheduled
181
  */
182
+ public function schedule_cache_flush( $forced = true ) {
183
  if ( $forced || ! wp_next_scheduled( 'pvc_flush_cached_counts' ) ) {
184
  wp_schedule_event( time(), 'post_views_counter_flush_interval', 'pvc_flush_cached_counts' );
185
  }
190
  */
191
  public function remove_cache_flush() {
192
  wp_clear_scheduled_hook( 'pvc_flush_cached_counts' );
193
+ remove_action( 'pvc_flush_cached_counts', array( Post_Views_Counter()->get_instance( 'cron' ), 'flush_cached_counts' ) );
194
  }
195
 
 
196
  /**
197
  * Load text domain
198
+ */
199
  public function load_textdomain() {
200
+ load_plugin_textdomain( 'post-views-counter', false, POST_VIEWS_COUNTER_REL_PATH . 'languages/' );
201
  }
202
 
 
203
  /**
204
  * Load pluggable template functions
205
+ */
206
  public function load_pluggable_functions() {
207
+ include_once(POST_VIEWS_COUNTER_PATH . 'includes/functions.php');
208
  }
209
 
 
210
  /**
211
  * Set instance of class
212
+ */
213
+ public function add_instance( $name, $instance ) {
214
  $this->instances[$name] = $instance;
215
  }
216
 
 
217
  /**
218
  * Get instance of a class
219
+ */
220
+ public function get_instance( $name ) {
221
+ if ( in_array( $name, array( 'counter', 'settings' ), true ) )
222
  return $this->instances[$name];
223
  }
224
 
 
225
  /**
226
  * Get allowed attribute
227
+ */
228
+ public function get_attribute( $attribute ) {
229
+ if ( in_array( $attribute, array( 'options', 'defaults' ), true ) ) {
230
+ switch ( func_num_args() ) {
231
  case 1:
232
  return $this->{$attribute};
233
 
234
  case 2:
235
+ return $this->{$attribute}[func_get_arg( 1 )];
236
 
237
  case 3:
238
+ return $this->{$attribute}[func_get_arg( 1 )][func_get_arg( 2 )];
239
 
240
  case 4:
241
+ return $this->{$attribute}[func_get_arg( 1 )][func_get_arg( 2 )][func_get_arg( 3 )];
242
  }
243
+ } else
 
244
  return false;
245
  }
246
 
 
247
  /**
248
  * Enqueue admin scripts and styles
249
+ */
250
+ public function admin_scripts_styles( $page ) {
251
+
252
  wp_register_style(
253
+ 'pvc-admin', POST_VIEWS_COUNTER_URL . '/css/admin.css'
 
254
  );
255
 
256
  wp_register_style(
257
+ 'pvc-chosen', POST_VIEWS_COUNTER_URL . '/assets/chosen/chosen.min.css'
 
258
  );
259
+
260
  wp_register_script(
261
+ 'pvc-admin-chosen', POST_VIEWS_COUNTER_URL . '/assets/chosen/chosen.jquery.min.js', array( 'jquery' ), $this->defaults['version']
 
 
 
262
  );
263
 
264
  wp_register_script(
265
+ 'pvc-admin-settings', POST_VIEWS_COUNTER_URL . '/js/admin-settings.js', array( 'jquery', 'pvc-admin-chosen' ), $this->defaults['version']
 
 
 
266
  );
267
+
268
  wp_register_script(
269
+ 'pvc-admin-post', POST_VIEWS_COUNTER_URL . '/js/admin-post.js', array( 'jquery' ), $this->defaults['version']
 
 
 
270
  );
271
+
272
  // load on PVC settings page
273
+ if ( $page === 'settings_page_post-views-counter' ) {
274
+
275
+ wp_enqueue_script( 'pvc-admin-chosen' );
276
+ wp_enqueue_script( 'pvc-admin-settings' );
277
 
278
  wp_localize_script(
279
+ 'pvc-admin-settings', 'pvcArgsSettings', array(
280
+ 'resetToDefaults' => __( 'Are you sure you want to reset these settings to defaults?', 'post-views-counter' )
 
 
281
  )
282
  );
283
 
284
+ wp_enqueue_style( 'pvc-chosen' );
285
+ wp_enqueue_style( 'pvc-admin' );
286
+
287
+ // load on single post page
288
+ } elseif ( $page = 'post.php' ) {
289
+
290
+ $post_types = Post_Views_Counter()->get_attribute( 'options', 'general', 'post_types_count' );
291
+
292
+ if ( ! in_array( get_post_type(), (array) $post_types ) )
293
  return;
294
+
295
+ wp_enqueue_style( 'pvc-admin' );
296
+ wp_enqueue_script( 'pvc-admin-post' );
297
  }
298
  }
299
+
300
+ /**
301
+ * Add links to plugin support forum.
302
+ */
303
+ public function plugin_extend_links( $links, $file ) {
304
+
305
+ if ( ! current_user_can( 'install_plugins' ) )
306
+ return $links;
307
+
308
+ $plugin = plugin_basename( __FILE__ );
309
+
310
+ if ( $file == $plugin ) {
311
+ return array_merge(
312
+ $links, array( sprintf( '<a href="http://www.dfactory.eu/support/forum/post-views-counter/" target="_blank">%s</a>', __( 'Support', 'post-views-counter' ) ) )
313
+ );
314
+ }
315
 
316
+ return $links;
317
+ }
318
 
319
  /**
320
  * Add link to settings page
321
+ */
322
+ public function plugin_settings_link( $links, $file ) {
323
+ if ( ! is_admin() || ! current_user_can( 'manage_options' ) )
324
  return $links;
325
 
326
  static $plugin;
327
 
328
+ $plugin = plugin_basename( __FILE__ );
329
 
330
+ if ( $file == $plugin ) {
331
+ $settings_link = sprintf( '<a href="%s">%s</a>', admin_url( 'options-general.php' ) . '?page=post-views-counter', __( 'Settings', 'post-views-counter' ) );
332
 
333
+ array_unshift( $links, $settings_link );
334
  }
335
 
336
  return $links;
337
  }
338
+
339
  }
340
 
341
  /**
344
  function Post_Views_Counter() {
345
  static $instance;
346
 
347
+ // first call to instance() initializes the plugin
348
+ if ( $instance === null || ! ($instance instanceof Post_Views_Counter) )
349
+ $instance = Post_Views_Counter::instance();
350
 
351
+ return $instance;
352
  }
353
 
354
+ Post_Views_Counter();
 
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: dfactory
3
  Donate link: http://www.dfactory.eu/
4
  Tags: counter, hits, postviews, post views, views, count
5
  Requires at least: 3.8.0
6
- Tested up to: 4.1.1
7
- Stable tag: 1.0.7
8
  License: MIT License
9
  License URI: http://opensource.org/licenses/MIT
10
 
@@ -34,6 +34,8 @@ For more information, check out plugin page at [dFactory](http://www.dfactory.eu
34
  * .pot file for translations included
35
 
36
  = Translations: =
 
 
37
  * Hebrew - by [Ahrale Shrem](http://atar4u.com/)
38
  * Polish - by Bartosz Arendt
39
  * Russian - by moonkir
@@ -60,6 +62,9 @@ No questions yet.
60
 
61
  == Changelog ==
62
 
 
 
 
63
  = 1.0.7 =
64
  * New: Possibility to manually set views count for each post
65
  * New: Plugin development moved to [dFactory GitHub Repository](https://github.com/dfactoryplugins)
@@ -87,5 +92,5 @@ Initial release
87
 
88
  == Upgrade Notice ==
89
 
90
- = 1.0.7 =
91
- * New: Possibility to manually set views count for each post
3
  Donate link: http://www.dfactory.eu/
4
  Tags: counter, hits, postviews, post views, views, count
5
  Requires at least: 3.8.0
6
+ Tested up to: 4.2
7
+ Stable tag: 1.0.8
8
  License: MIT License
9
  License URI: http://opensource.org/licenses/MIT
10
 
34
  * .pot file for translations included
35
 
36
  = Translations: =
37
+
38
+ * Croation translation - by [Tomas Trkulja](http://zytzagoo.net/blog/)
39
  * Hebrew - by [Ahrale Shrem](http://atar4u.com/)
40
  * Polish - by Bartosz Arendt
41
  * Russian - by moonkir
62
 
63
  == Changelog ==
64
 
65
+ = 1.0.8 =
66
+ * New: Croation translation, thanks to [Tomas Trkulja](http://zytzagoo.net/blog/)
67
+
68
  = 1.0.7 =
69
  * New: Possibility to manually set views count for each post
70
  * New: Plugin development moved to [dFactory GitHub Repository](https://github.com/dfactoryplugins)
92
 
93
  == Upgrade Notice ==
94
 
95
+ = 1.0.8 =
96
+ * New: Croation translation, thanks to [Tomas Trkulja](http://zytzagoo.net/blog/)