PluginProbe ʕ •ᴥ•ʔ
Post Views Counter / 1.3.6
Post Views Counter v1.3.6
1.7.13 1.7.12 1.7.11 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.2 1.3.2.1 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.7.0 1.7.1 1.7.10 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9
post-views-counter / includes / columns.php
post-views-counter / includes Last commit date
ajax.php 7 years ago columns.php 4 years ago counter.php 4 years ago crawler-detect.php 6 years ago cron.php 6 years ago dashboard.php 4 years ago frontend.php 6 years ago functions.php 4 years ago query.php 6 years ago settings.php 4 years ago update.php 6 years ago widgets.php 4 years ago
columns.php
617 lines
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Post_Views_Counter_Columns class.
8 *
9 * @class Post_Views_Counter_Columns
10 */
11 class Post_Views_Counter_Columns {
12
13 public function __construct() {
14 // actions
15 add_action( 'admin_init', array( $this, 'register_new_column' ) );
16 add_action( 'post_submitbox_misc_actions', array( $this, 'submitbox_views' ) );
17 add_action( 'attachment_submitbox_misc_actions', array( $this, 'submitbox_views' ) );
18 add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
19 add_action( 'edit_attachment', array( $this, 'save_post' ), 10 );
20 add_action( 'bulk_edit_custom_box', array( $this, 'quick_edit_custom_box' ), 10, 2 );
21 add_action( 'quick_edit_custom_box', array( $this, 'quick_edit_custom_box' ), 10, 2 );
22 add_action( 'wp_ajax_save_bulk_post_views', array( $this, 'save_bulk_post_views' ) );
23 add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 100 );
24 add_action( 'wp', array( $this, 'admin_bar_maybe_add_style' ) );
25 add_action( 'admin_init', array( $this, 'admin_bar_maybe_add_style' ) );
26
27 // gutenberg
28 add_action( 'plugins_loaded', array( $this, 'init_gutenberg' ) );
29 }
30
31 /**
32 * Init Gutenberg
33 */
34 public function init_gutenberg() {
35 $block_editor = has_action( 'enqueue_block_assets' );
36 $gutenberg = function_exists( 'gutenberg_can_edit_post_type' );
37
38 if ( ! $block_editor && ! $gutenberg ) {
39 return;
40 }
41
42 add_action( 'add_meta_boxes', array( $this, 'gutenberg_add_meta_box' ) );
43 add_action( 'rest_api_init', array( $this, 'gutenberg_rest_api_init' ) );
44 add_action( 'enqueue_block_editor_assets', array( $this, 'gutenberg_enqueue_scripts' ) );
45 }
46
47 /**
48 * Register Gutenberg Metabox.
49 */
50 public function gutenberg_add_meta_box() {
51 add_meta_box( 'post_views_meta_box', __( 'Post Views', 'post-views-counter' ), '', 'post', '', '', array(
52 '__back_compat_meta_box' => false,
53 '__block_editor_compatible_meta_box' => true
54 ) );
55 }
56
57 /**
58 * Register REST API Gutenberg endpoints.
59 */
60 public function gutenberg_rest_api_init() {
61 // get views route
62 register_rest_route(
63 'post-views-counter',
64 '/update-post-views/',
65 array(
66 'methods' => array( 'POST' ),
67 'callback' => array( $this, 'gutenberg_update_callback' ),
68 'permission_callback' => array( $this, 'check_rest_route_permissions' ),
69 'args' => array(
70 'id' => array(
71 'sanitize_callback' => 'absint',
72 )
73 )
74 )
75 );
76 }
77
78 /**
79 * Check whether user has permissions to perform post views update in Gutenberg editor.
80 *
81 * @param object $request WP_REST_Request
82 * @return bool|WP_Error
83 */
84 public function check_rest_route_permissions( $request ) {
85 // break if current user can't edit this post
86 if ( ! current_user_can( 'edit_post', (int) $request->get_param( 'id' ) ) )
87 return new WP_Error( 'pvc-user-not-allowed', __( 'You are not allowed to edit this item.', 'post-views-counter' ) );
88
89 // break if views editing is restricted
90 if ( (bool) Post_Views_Counter()->options['general']['restrict_edit_views'] === true && ! current_user_can( apply_filters( 'pvc_restrict_edit_capability', 'manage_options' ) ) )
91 return new WP_Error( 'pvc-user-not-allowed', __( 'You are not allowed to edit this item.', 'post-views-counter' ) );
92
93 return true;
94 }
95
96 /**
97 * REST API Callback for Gutenberg endpoint.
98 *
99 * @param array $data
100 * @return array|int
101 */
102 public function gutenberg_update_callback( $data ) {
103 $post_id = ! empty( $data['id'] ) ? (int) $data['id'] : 0;
104 $post_views = ! empty( $data['post_views'] ) ? (int) $data['post_views'] : 0;
105
106 // get countable post types
107 $post_types = Post_Views_Counter()->options['general']['post_types_count'];
108
109 // check if post exists
110 $post = get_post( $post_id );
111
112 // whether to count this post type or not
113 if ( empty( $post_types ) || empty( $post ) || ! in_array( $post->post_type, $post_types, true ) )
114 return wp_send_json_error( __( 'Invalid post ID.', 'post-views-counter' ) );
115
116 // break if current user can't edit this post
117 if ( ! current_user_can( 'edit_post', $post_id ) )
118 return wp_send_json_error( __( 'You are not allowed to edit this item.', 'post-views-counter' ) );
119
120 // break if views editing is restricted
121 if ( (bool) Post_Views_Counter()->options['general']['restrict_edit_views'] === true && ! current_user_can( apply_filters( 'pvc_restrict_edit_capability', 'manage_options' ) ) )
122 return wp_send_json_error( __( 'You are not allowed to edit this item.', 'post-views-counter' ) );
123
124 global $wpdb;
125
126 pvc_update_post_views( $post_id, $post_views );
127
128 do_action( 'pvc_after_update_post_views_count', $post_id );
129
130 return $post_id;
131 }
132
133 /**
134 * Enqueue front end and editor JavaScript and CSS
135 */
136 public function gutenberg_enqueue_scripts() {
137 // enqueue the bundled block JS file
138 wp_enqueue_script(
139 'pvc-gutenberg',
140 POST_VIEWS_COUNTER_URL . '/js/gutenberg.min.js',
141 array( 'wp-i18n', 'wp-edit-post', 'wp-element', 'wp-editor', 'wp-components', 'wp-data', 'wp-plugins', 'wp-api' ),
142 Post_Views_Counter()->defaults['version']
143 );
144
145 // restrict editing
146 $restrict = (bool) Post_Views_Counter()->options['general']['restrict_edit_views'];
147 $can_edit = $restrict === false || ( $restrict === true && current_user_can( apply_filters( 'pvc_restrict_edit_capability', 'manage_options' ) ) );
148
149 $js_args = array(
150 'postID' => get_the_ID(),
151 'postViews' => pvc_get_post_views( get_the_ID() ),
152 'canEdit' => $can_edit,
153 'nonce' => wp_create_nonce( 'wp_rest' ),
154 'textPostViews' => __( 'Post Views', 'post-views-counter' ),
155 'textHelp' => __( 'Adjust the views count for this post.', 'post-views-counter' ),
156 'textCancel' => __( 'Cancel', 'post-views-counter' )
157 );
158
159 wp_localize_script(
160 'pvc-gutenberg',
161 'pvcEditorArgs',
162 $js_args
163 );
164
165 // enqueue frontend and editor block styles
166 wp_enqueue_style(
167 'pvc-gutenberg',
168 POST_VIEWS_COUNTER_URL . '/css/gutenberg.min.css', '',
169 Post_Views_Counter()->defaults['version']
170 );
171 }
172
173 /**
174 * Output post views for single post.
175 *
176 * @global object $post
177 * @return mixed
178 */
179 public function submitbox_views() {
180 global $post;
181
182 if ( ! in_array( $post->post_type, (array) Post_Views_Counter()->options['general']['post_types_count'] ) )
183 return;
184
185 // break if current user can't edit this post
186 if ( ! current_user_can( 'edit_post', $post->ID ) )
187 return;
188
189 // get total post views
190 $count = (int) pvc_get_post_views( $post->ID ); ?>
191
192 <div class="misc-pub-section" id="post-views">
193
194 <?php wp_nonce_field( 'post_views_count', 'pvc_nonce' ); ?>
195
196 <span id="post-views-display">
197 <?php echo __( 'Post Views', 'post-views-counter' ) . ': <b>' . number_format_i18n( $count ) . '</b>'; ?>
198 </span>
199
200 <?php
201 // restrict editing
202 $restrict = (bool) Post_Views_Counter()->options['general']['restrict_edit_views'];
203
204 if ( $restrict === false || ( $restrict === true && current_user_can( apply_filters( 'pvc_restrict_edit_capability', 'manage_options' ) ) ) ) {
205 ?>
206 <a href="#post-views" class="edit-post-views hide-if-no-js"><?php _e( 'Edit', 'post-views-counter' ); ?></a>
207
208 <div id="post-views-input-container" class="hide-if-js">
209
210 <p><?php _e( 'Adjust the views count for this post.', 'post-views-counter' ); ?></p>
211 <input type="hidden" name="current_post_views" id="post-views-current" value="<?php echo $count; ?>" />
212 <input type="text" name="post_views" id="post-views-input" value="<?php echo $count; ?>"/><br />
213 <p>
214 <a href="#post-views" class="save-post-views hide-if-no-js button"><?php _e( 'OK', 'post-views-counter' ); ?></a>
215 <a href="#post-views" class="cancel-post-views hide-if-no-js"><?php _e( 'Cancel', 'post-views-counter' ); ?></a>
216 </p>
217
218 </div>
219 <?php
220 }
221 ?>
222
223 </div>
224 <?php
225 }
226
227 /**
228 * Save post views data.
229 *
230 * @param int $post_id
231 * @param object $post
232 */
233 public function save_post( $post_id, $post = null ) {
234 if ( is_null( $post ) )
235 $post_type = get_post_type( $post_id );
236 else
237 $post_type = $post->post_type;
238
239 // break if doing autosave
240 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
241 return $post_id;
242
243 // break if current user can't edit this post
244 if ( ! current_user_can( 'edit_post', $post_id ) )
245 return $post_id;
246
247 // is post views set
248 if ( ! isset( $_POST['post_views'] ) )
249 return $post_id;
250
251 // cast numeric post views
252 $post_views = (int) $_POST['post_views'];
253
254 // unchanged post views value?
255 if ( isset( $_POST['current_post_views'] ) && $post_views === (int) $_POST['current_post_views'] )
256 return $post_id;
257
258 // break if post views in not one of the selected
259 $post_types = Post_Views_Counter()->options['general']['post_types_count'];
260
261 if ( ! in_array( $post_type, (array) $post_types ) )
262 return $post_id;
263
264 // break if views editing is restricted
265 $restrict = (bool) Post_Views_Counter()->options['general']['restrict_edit_views'];
266
267 if ( $restrict === true && ! current_user_can( apply_filters( 'pvc_restrict_edit_capability', 'manage_options' ) ) )
268 return $post_id;
269
270 // validate data
271 if ( ! isset( $_POST['pvc_nonce'] ) || ! wp_verify_nonce( $_POST['pvc_nonce'], 'post_views_count' ) )
272 return $post_id;
273
274 pvc_update_post_views( $post_id, $post_views );
275
276 do_action( 'pvc_after_update_post_views_count', $post_id );
277 }
278
279 /**
280 * Register post views column for specific post types
281 */
282 public function register_new_column() {
283 $post_types = Post_Views_Counter()->options['general']['post_types_count'];
284
285 if ( ! empty( $post_types ) ) {
286 foreach ( $post_types as $post_type ) {
287 if ( $post_type === 'attachment' ) {
288 // actions
289 add_action( 'manage_media_custom_column', array( $this, 'add_new_column_content' ), 10, 2 );
290
291 // filters
292 add_filter( 'manage_media_columns', array( $this, 'add_new_column' ) );
293 add_filter( 'manage_upload_sortable_columns', array( $this, 'register_sortable_custom_column' ) );
294 } else {
295 // actions
296 add_action( 'manage_' . $post_type . '_posts_custom_column', array( $this, 'add_new_column_content' ), 10, 2 );
297
298 // filters
299 add_filter( 'manage_' . $post_type . '_posts_columns', array( $this, 'add_new_column' ) );
300 add_filter( 'manage_edit-' . $post_type . '_sortable_columns', array( $this, 'register_sortable_custom_column' ) );
301
302 if ( class_exists( 'bbPress' ) ) {
303 if ( $post_type === 'forum' )
304 add_filter( 'bbp_admin_forums_column_headers', array( $this, 'add_new_column' ) );
305 elseif ( $post_type === 'topic' )
306 add_filter( 'bbp_admin_topics_column_headers', array( $this, 'add_new_column' ) );
307 }
308 }
309 }
310 }
311 }
312
313 /**
314 * Register sortable post views column.
315 *
316 * @param array $columns
317 * @return array
318 */
319 public function register_sortable_custom_column( $columns ) {
320 // add new sortable column
321 $columns['post_views'] = 'post_views';
322
323 return $columns;
324 }
325
326 /**
327 * Add post views column.
328 *
329 * @param array $columns
330 * @return array
331 */
332 public function add_new_column( $columns ) {
333 $offset = 0;
334
335 if ( isset( $columns['date'] ) )
336 $offset++;
337
338 if ( isset( $columns['comments'] ) )
339 $offset++;
340
341 if ( $offset > 0 ) {
342 $date = array_slice( $columns, -$offset, $offset, true );
343
344 foreach ( $date as $column => $name ) {
345 unset( $columns[$column] );
346 }
347
348 $columns['post_views'] = '<span class="dash-icon dashicons dashicons-chart-bar" title="' . __( 'Post Views', 'post-views-counter' ) . '"></span><span class="dash-title">' . __( 'Post Views', 'post-views-counter' ) . '</span>';
349
350 foreach ( $date as $column => $name ) {
351 $columns[$column] = $name;
352 }
353 } else
354 $columns['post_views'] = '<span class="dash-icon dashicons dashicons-chart-bar" title="' . __( 'Post Views', 'post-views-counter' ) . '"></span><span class="dash-title">' . __( 'Post Views', 'post-views-counter' ) . '</span>';
355
356 return $columns;
357 }
358
359 /**
360 * Add post views column content.
361 *
362 * @param string $column_name
363 * @param int $id
364 * @return muxed
365 */
366 public function add_new_column_content( $column_name, $id ) {
367 if ( $column_name === 'post_views' ) {
368 // get total post views
369 $count = pvc_get_post_views( $id );
370
371 echo $count;
372 }
373 }
374
375 /**
376 * Handle quick edit.
377 *
378 * @global string $pagenow
379 * @param string $column_name
380 * @return mixed
381 */
382 function quick_edit_custom_box( $column_name, $post_type ) {
383 global $pagenow, $post;
384
385 if ( $pagenow !== 'edit.php' )
386 return;
387
388 if ( $column_name !== 'post_views' )
389 return;
390
391 if ( ! Post_Views_Counter()->options['general']['post_views_column'] || ! in_array( $post_type, Post_Views_Counter()->options['general']['post_types_count'] ) )
392 return;
393
394 // break if views editing is restricted
395 $restrict = (bool) Post_Views_Counter()->options['general']['restrict_edit_views'];
396
397 if ( $restrict === true && ! current_user_can( apply_filters( 'pvc_restrict_edit_capability', 'manage_options' ) ) )
398 return;
399
400 ?>
401 <fieldset class="inline-edit-col-left">
402 <div id="inline-edit-post_views" class="inline-edit-col">
403 <label class="inline-edit-group">
404 <span class="title"><?php _e( 'Post Views', 'post-views-counter' ); ?></span>
405 <span class="input-text-wrap"><input type="text" name="post_views" class="title text" value=""></span>
406 <input type="hidden" name="current_post_views" value="" />
407 <?php wp_nonce_field( 'post_views_count', 'pvc_nonce' ); ?>
408 </label>
409 </div>
410 </fieldset>
411 <?php
412 }
413
414 /**
415 * Bulk save post views.
416 *
417 * @global object $wpdb;
418 * @return type
419 */
420 function save_bulk_post_views() {
421 if ( ! isset( $_POST['post_views'] ) )
422 $count = null;
423 else {
424 $count = trim( $_POST['post_views'] );
425
426 if ( is_numeric( $_POST['post_views'] ) ) {
427 $count = (int) $_POST['post_views'];
428
429 if ( $count < 0 )
430 $count = 0;
431 } else
432 $count = null;
433 }
434
435 $post_ids = ( ! empty( $_POST['post_ids'] ) && is_array( $_POST['post_ids'] ) ) ? array_map( 'absint', $_POST['post_ids'] ) : array();
436
437 if ( is_null( $count ) )
438 exit;
439
440 // break if views editing is restricted
441 $restrict = (bool) Post_Views_Counter()->options['general']['restrict_edit_views'];
442
443 if ( $restrict === true && ! current_user_can( apply_filters( 'pvc_restrict_edit_capability', 'manage_options' ) ) )
444 exit;
445
446 if ( ! empty( $post_ids ) ) {
447 foreach ( $post_ids as $post_id ) {
448
449 // break if current user can't edit this post
450 if ( ! current_user_can( 'edit_post', $post_id ) )
451 continue;
452
453 global $wpdb;
454
455 // insert or update db post views count
456 $wpdb->query(
457 $wpdb->prepare( "
458 INSERT INTO " . $wpdb->prefix . "post_views (id, type, period, count)
459 VALUES (%d, %d, %s, %d)
460 ON DUPLICATE KEY UPDATE count = %d", $post_id, 4, 'total', $count, $count
461 )
462 );
463 }
464 }
465
466 exit;
467 }
468
469 /**
470 * Add admin bar stats to a post.
471 */
472 public function admin_bar_menu( $admin_bar ) {
473 // get main instance
474 $pvc = Post_Views_Counter();
475
476 // statistics enabled?
477 if ( ! apply_filters( 'pvc_display_toolbar_statistics', $pvc->options['display']['toolbar_statistics'] ) )
478 return;
479
480 $post = null;
481
482 if ( is_admin() && ! wp_doing_ajax() ) {
483 global $pagenow;
484
485 $post = $pagenow == 'post.php' && ! empty( $_GET['post'] ) ? get_post( (int) $_GET['post'] ) : $post;
486 } elseif ( is_singular() )
487 global $post;
488
489 // get countable post types
490 $post_types = Post_Views_Counter()->options['general']['post_types_count'];
491
492 // whether to count this post type or not
493 if ( empty( $post_types ) || empty( $post ) || ! in_array( $post->post_type, $post_types, true ) )
494 return;
495
496 $dt = new DateTime();
497
498 // get post views
499 $views = pvc_get_views( array(
500 'post_id' => $post->ID,
501 'post_type' => $post->post_type,
502 'fields' => 'date=>views',
503 'views_query' => array(
504 'year' => $dt->format( 'Y' ),
505 'month' => $dt->format( 'm' )
506 )
507 ) );
508
509 $graph = '';
510
511 // get highest value
512 $views_copy = $views;
513
514 arsort( $views_copy, SORT_NUMERIC );
515
516 $highest = reset( $views_copy );
517
518 // find the multiplier
519 $multiplier = $highest * 0.05;
520
521 // generate ranges
522 $ranges = array();
523
524 for ( $i = 1; $i <= 20; $i ++ ) {
525 $ranges[$i] = round( $multiplier * $i );
526 }
527
528 // create graph
529 foreach ( $views as $date => $count ) {
530 $count_class = 0;
531
532 if ( $count > 0 ) {
533 foreach ( $ranges as $index => $range ) {
534 if ( $count <= $range ) {
535 $count_class = $index;
536 break;
537 }
538 }
539 }
540
541 $graph .= '<span class="pvc-line-graph pvc-line-graph-' . $count_class . '" title="' . sprintf( _n( '%s post view', '%s post views', $count, 'post-views-counter' ), number_format_i18n( $count ) ) . '"></span>';
542 }
543
544 $admin_bar->add_menu(
545 [
546 'id' => 'pvc-post-views',
547 'title' => '<span class="pvc-graph-container">' . $graph . '</span>',
548 'href' => false,
549 'meta' => [
550 'title' => false
551 ]
552 ]
553 );
554 }
555
556 /**
557 * Maybe add admin CSS.
558 */
559 public function admin_bar_maybe_add_style() {
560 // get main instance
561 $pvc = Post_Views_Counter();
562
563 // statistics enabled?
564 if ( ! $pvc->options['display']['toolbar_statistics'] )
565 return;
566
567 $post = null;
568
569 if ( is_admin() && ! wp_doing_ajax() ) {
570 global $pagenow;
571
572 $post = ( $pagenow === 'post.php' && ! empty( $_GET['post'] ) ) ? get_post( (int) $_GET['post'] ) : $post;
573 } elseif ( is_singular() )
574 global $post;
575
576 // get countable post types
577 $post_types = $pvc->options['general']['post_types_count'];
578
579 // whether to count this post type or not
580 if ( empty( $post_types ) || empty( $post ) || ! in_array( $post->post_type, $post_types, true ) )
581 return;
582
583 // on backend area
584 add_action( 'admin_head', array( $this, 'admin_bar_css' ) );
585
586 // on frontend area
587 add_action( 'wp_head', array( $this, 'admin_bar_css' ) );
588 }
589
590 /**
591 * Add admin CSS.
592 */
593 public function admin_bar_css() {
594 $html = '
595 <style type="text/css">
596 #wp-admin-bar-pvc-post-views .pvc-graph-container { padding-top: 6px; padding-bottom: 6px; position: relative; display: block; height: 100%; box-sizing: border-box; }
597 #wp-admin-bar-pvc-post-views .pvc-line-graph {
598 display: inline-block;
599 width: 1px;
600 margin-right: 1px;
601 background-color: #ccc;
602 vertical-align: baseline;
603 }
604 #wp-admin-bar-pvc-post-views .pvc-line-graph:hover { background-color: #eee; }
605 #wp-admin-bar-pvc-post-views .pvc-line-graph-0 { height: 1% }';
606
607 for ( $i = 1; $i <= 20; $i ++ ) {
608 $html .= '
609 #wp-admin-bar-pvc-post-views .pvc-line-graph-' . $i . ' { height: ' . $i * 5 . '% }';
610 }
611
612 $html .= '
613 </style>';
614
615 echo $html;
616 }
617 }