PluginProbe ʕ •ᴥ•ʔ
Post Views Counter / 1.7.13
Post Views Counter v1.7.13
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 / class-dashboard.php
post-views-counter / includes Last commit date
class-admin.php 2 weeks ago class-columns-modal.php 2 weeks ago class-columns.php 2 weeks ago class-counter.php 2 weeks ago class-crawler-detect.php 2 weeks ago class-cron.php 2 weeks ago class-dashboard.php 2 weeks ago class-emails-mailer.php 2 weeks ago class-emails-period.php 2 weeks ago class-emails-query.php 2 weeks ago class-emails-scheduler.php 2 weeks ago class-emails-template.php 2 weeks ago class-emails.php 2 weeks ago class-frontend.php 2 weeks ago class-functions.php 2 weeks ago class-import.php 2 weeks ago class-integration-gutenberg.php 2 weeks ago class-integrations.php 2 weeks ago class-query.php 2 weeks ago class-settings-api.php 2 weeks ago class-settings-display.php 2 weeks ago class-settings-emails.php 2 weeks ago class-settings-general.php 2 weeks ago class-settings-integrations.php 2 weeks ago class-settings-other.php 2 weeks ago class-settings-reports.php 2 weeks ago class-settings.php 2 weeks ago class-toolbar.php 2 weeks ago class-traffic-signals.php 2 weeks ago class-update.php 2 weeks ago class-widgets.php 2 weeks ago functions.php 2 weeks ago
class-dashboard.php
691 lines
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Post_Views_Counter_Dashboard class.
8 *
9 * @class Post_Views_Counter_Dashboard
10 */
11 class Post_Views_Counter_Dashboard {
12
13 private $widget_items = [];
14
15 /**
16 * Class constructor.
17 *
18 * @return void
19 */
20 public function __construct() {
21 // actions
22 add_action( 'admin_init', [ $this, 'init_admin_dashboard' ] );
23 }
24
25 /**
26 * Dashboard initialization.
27 *
28 * @global string $pagenow
29 *
30 * @return void
31 */
32 public function init_admin_dashboard() {
33 global $pagenow;
34
35 // setup widget items
36 $this->setup_widget_items();
37
38 // do it only on dashboard page
39 if ( $pagenow === 'index.php' ) {
40 // filter user_can_see_stats
41 if ( ! apply_filters( 'pvc_user_can_see_stats', current_user_can( 'publish_posts' ) ) )
42 return;
43
44 add_action( 'wp_dashboard_setup', [ $this, 'wp_dashboard_setup' ], 1 );
45 add_action( 'admin_enqueue_scripts', [ $this, 'admin_scripts_styles' ] );
46 // ajax endpoints
47 } elseif ( $pagenow === 'admin-ajax.php' ) {
48 add_action( 'wp_ajax_pvc_dashboard_post_most_viewed', [ $this, 'dashboard_post_most_viewed' ] );
49 add_action( 'wp_ajax_pvc_dashboard_post_views_chart', [ $this, 'dashboard_post_views_chart' ] );
50 add_action( 'wp_ajax_pvc_dashboard_user_options', [ $this, 'update_dashboard_user_options' ] );
51 }
52 }
53
54 /**
55 * Add dashboard widget.
56 *
57 * @return void
58 */
59 public function wp_dashboard_setup() {
60 // add dashboard widget
61 wp_add_dashboard_widget( 'pvc_dashboard', __( 'Post Views', 'post-views-counter' ), [ $this, 'dashboard_widget' ] );
62 }
63
64 /**
65 * Enqueue admin scripts and styles.
66 *
67 * @return void
68 */
69 public function admin_scripts_styles() {
70 // get main instance
71 $pvc = Post_Views_Counter();
72
73 // styles
74 wp_enqueue_style( 'pvc-admin-dashboard', POST_VIEWS_COUNTER_URL . '/css/admin-dashboard.css', [], $pvc->defaults['version'] );
75 wp_enqueue_style( 'pvc-microtip', POST_VIEWS_COUNTER_URL . '/assets/microtip/microtip.min.css', [], '1.0.0' );
76
77 // scripts
78 wp_enqueue_script( 'pvc-admin-dashboard', POST_VIEWS_COUNTER_URL . '/js/admin-dashboard.js', [ 'jquery', 'pvc-chartjs' ], $pvc->defaults['version'], true );
79
80 // prepare script data
81 $script_data = [
82 'ajaxURL' => admin_url( 'admin-ajax.php' ),
83 'nonce' => wp_create_nonce( 'pvc-dashboard-widget' ),
84 'nonceUser' => wp_create_nonce( 'pvc-dashboard-user-options' ),
85 'i18n' => [
86 'loadError' => __( 'Failed to load this widget.', 'post-views-counter' ),
87 'retry' => __( 'Retry', 'post-views-counter' ),
88 ]
89 ];
90
91 $script_data = apply_filters( 'pvc_admin_dashboard_script_data', $script_data );
92
93 wp_add_inline_script( 'pvc-admin-dashboard', 'var pvcArgs = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
94 }
95
96 /**
97 * Setup dashboard widget items.
98 *
99 * @return void
100 */
101 private function setup_widget_items() {
102 // standard items
103 $items = [
104 [
105 'id' => 'post-views',
106 'title' => __( 'Post Views', 'post-views-counter' ),
107 'description' => __( 'Displays a chart of most viewed post types.', 'post-views-counter' ),
108 'content' => '<canvas id="pvc-post-views-chart" height="' . (int) $this->calculate_canvas_size( Post_Views_Counter()->options['general']['post_types_count'] ) . '"></canvas>',
109 'position' => 2
110 ],
111 [
112 'id' => 'post-most-viewed',
113 'title' => __( 'Top Posts', 'post-views-counter' ),
114 'description' => __( 'Displays a list of most viewed single posts or pages.', 'post-views-counter' ),
115 'content' => '<div id="pvc-post-most-viewed-content" class="pvc-table-responsive"></div>',
116 'position' => 3
117 ]
118 ];
119
120 // filter items, do not allow to remove main items
121 $new_items = apply_filters( 'pvc_dashboard_widget_items', [] );
122
123 // any new items?
124 if ( is_array( $new_items ) && ! empty( $new_items ) ) {
125 foreach ( $new_items as $item ) {
126 // add new item
127 array_push( $items, $item );
128 }
129 }
130
131 // sort dashboard items by position
132 array_multisort( array_column( $items, 'position' ), SORT_ASC, SORT_NUMERIC, $items );
133
134 // set widget items
135 $this->widget_items = $items;
136 }
137
138 public function get_widget_items() {
139 // return widget items
140 return $this->widget_items;
141 }
142
143 /**
144 * Calculate canvas height based on number of legend items.
145 *
146 * @param array $data
147 * @param bool $expression
148 * @return int
149 */
150 public function calculate_canvas_size( $data, $expression = true ) {
151 if ( $expression && ! empty( $data ) ) {
152 // treat every 4 legend items as 1 line - 23 pixels
153 $height = 23 * ( (int) ceil( count( $data ) / 4 ) - 1 );
154 } else
155 $height = 0;
156
157 return (int) ( 170 + $height );
158 }
159
160 /**
161 * Render dashboard widget.
162 *
163 * @return void
164 */
165 public function dashboard_widget() {
166 // get user options
167 $user_options = get_user_meta( get_current_user_id(), 'pvc_dashboard', true );
168
169 // check whether the related features are available
170 $is_pro = class_exists( 'Post_Views_Counter_Pro' );
171
172 // empty options?
173 if ( empty( $user_options ) || ! is_array( $user_options ) )
174 $user_options = [];
175
176 // sanitize options
177 $user_options = map_deep( $user_options, 'sanitize_text_field' );
178
179 // get menu items
180 $menu_items = ! empty( $user_options['menu_items'] ) ? $user_options['menu_items'] : [];
181
182 // get widget items
183 $items = $this->widget_items;
184
185 $html = '
186 <div id="pvc-dashboard-accordion" class="pvc-accordion">';
187
188 foreach ( $items as $item ) {
189 $html .= $this->generate_dashboard_widget_item( $item, $menu_items );
190 }
191
192 if ( ! $is_pro ) {
193 $html .= '
194 <div class="pvc-dashboard-unlock">
195 <div class="pvc-dashboard-unlock-content">
196 <h3>' . esc_html__( 'More Insights', 'post-views-counter' ) . '</h3>
197 <ul>
198 <li>' . esc_html__( 'Go beyond basic post views.', 'post-views-counter' ) . '</li>
199 <li>' . esc_html__( 'See site views, referrers, popular searches, top users, and more.', 'post-views-counter' ) . '</li>
200 </ul>
201 <a href="' . esc_url( Post_Views_Counter()->get_postviewscounter_url( '/upgrade/', 'button', 'upgrade-to-pro', 'dashboard-unlock-button', 'free' ) ) . '" class="button button-secondary" target="_blank">' . esc_html__( 'Unlock more insights', 'post-views-counter' ) . ' &rarr;</a>
202 </div>
203 </div>';
204 }
205
206 $html .= '
207 <div class="pvc-dashboard-block"><span>' . esc_html__( 'Powered by', 'post-views-counter' ) . ' <a href="' . esc_url( Post_Views_Counter()->get_postviewscounter_url( '/', 'link', 'powered-by', 'dashboard-powered-by-link', 'free' ) ) . '" target="_blank">Post Views Counter</a></span></div>
208 </div>';
209
210 // Output is admin-only, content is already escaped, and contains dynamic elements like canvas
211 echo $html;
212 }
213
214 /**
215 * Generate dashboard widget item HTML.
216 *
217 * @param array $item
218 * @param array $menu_items
219 *
220 * @return string
221 */
222 public function generate_dashboard_widget_item( $item, $menu_items ) {
223 // get allowed html tags
224 $allowed_html = wp_kses_allowed_html( 'post' );
225 $allowed_html['canvas'] = [
226 'id' => [],
227 'height' => []
228 ];
229
230 ob_start(); ?>
231
232 <div id="pvc-<?php esc_attr_e( $item['id'] ); ?>" class="pvc-accordion-item<?php echo ( in_array( $item['id'], $menu_items, true ) ? ' pvc-collapsed' : '' ); ?>">
233 <div class="pvc-accordion-header">
234 <div class="pvc-accordion-toggle"><span class="pvc-accordion-title"><?php esc_html_e( $item['title'] ); ?></span><span class="pvc-tooltip" aria-label="<?php esc_html_e( $item['description'] ); ?>" data-microtip-position="top" data-microtip-size="large" role="tooltip"><span class="pvc-tooltip-icon"></span></span></div>
235 <div class="pvc-accordion-actions">
236 <!--<a href="javascript:void(0);" class="pvc-accordion-action dashicons dashicons-admin-generic"></a>-->
237 <a href="javascript:void(0);" class="pvc-accordion-action pvc-toggle-indicator"></a>
238 </div>
239 </div>
240 <div class="pvc-accordion-content">
241 <div class="pvc-dashboard-container loading">
242 <div class="pvc-dashboard-content-top">
243 <?php do_action( 'pvc_dashboard_widget_content_top', $item['id'] ); ?>
244 </div>
245 <div class="pvc-data-container">
246 <?php echo wp_kses( $item['content'], $allowed_html ); ?>
247 <div class="pvc-dashboard-message" aria-live="polite"></div>
248 <span class="spinner"></span>
249 </div>
250 <div class="pvc-dashboard-content-bottom">
251 <div class="pvc-date-nav pvc-months">
252 <?php
253 // generate dates
254 echo wp_kses_post( $this->generate_months( current_time( 'timestamp', false ), $item['id'] ) );
255 ?>
256 </div>
257 <?php do_action( 'pvc_dashboard_widget_content_bottom', $item['id'] ); ?>
258 </div>
259 </div>
260 </div>
261 </div>
262
263 <?php
264 // Output current buffer
265 return ob_get_clean();
266 }
267
268 /**
269 * Render dashboard widget with post views.
270 *
271 * @return void
272 */
273 public function dashboard_post_views_chart() {
274 if ( ! apply_filters( 'pvc_user_can_see_stats', current_user_can( 'publish_posts' ) ) || ! check_ajax_referer( 'pvc-dashboard-widget', 'nonce' ) )
275 wp_die( __( 'You do not have permission to access this page.', 'post-views-counter' ) );
276
277 // get period
278 $period = isset( $_POST['period'] ) && ! empty( $_POST['period'] ) ? preg_replace( '/[^a-z0-9_|]/', '', $_POST['period'] ) : apply_filters( 'pvc_dashboard_widget_default_period', 'this_month', 'post-views' );
279
280 // get post types
281 $post_types = Post_Views_Counter()->options['general']['post_types_count'];
282
283 // empty options?
284 if ( empty( $post_types ) || ! is_array( $post_types ) )
285 $post_types = [];
286
287 // sanitize post_types
288 $post_types = map_deep( $post_types, 'sanitize_text_field' );
289
290 // get dashboard user options
291 $user_options = $this->get_dashboard_user_options( get_current_user_id(), 'post_types' );
292
293 // empty options?
294 if ( empty( $user_options ) || ! is_array( $user_options ) )
295 $user_options = [];
296
297 // sanitize options
298 $user_options = map_deep( $user_options, 'sanitize_text_field' );
299
300 // get colors
301 $colors = Post_Views_Counter()->functions->get_colors();
302
303 // parameters to be used in filter
304 $args = [
305 'widget' => 'post_views',
306 'period' => $period,
307 'post_types' => $post_types,
308 'user_options' => $user_options
309 ];
310
311 $data = [
312 'widget' => 'post-views',
313 'design' => [
314 'fill' => true,
315 'backgroundColor' => 'rgba(' . $colors['r'] . ',' . $colors['g'] . ',' . $colors['b'] . ', 0.2)',
316 'borderColor' => 'rgba(' . $colors['r'] . ',' . $colors['g'] . ',' . $colors['b'] . ', 1)',
317 'borderWidth' => 1.2,
318 'borderDash' => [],
319 'pointBorderColor' => 'rgba(' . $colors['r'] . ',' . $colors['g'] . ',' . $colors['b'] . ', 1)',
320 'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
321 'pointBorderWidth' => 1.2
322 ],
323 'data' => [
324 'datasets' => [
325 [
326 'label' => __( 'Total Views', 'post-views-counter' ),
327 'post_type' => '_pvc_total_views',
328 'hidden' => in_array( '_pvc_total_views', $user_options, true ),
329 'data' => []
330 ]
331 ]
332 ],
333 ];
334
335 // convert period
336 $time = pvc_period2timestamp( $period );
337
338 // get date chunks
339 $date = date( 'Y m W d t', $time );
340 $date_chunks = explode( ' ', $date );
341
342 // get date
343 $year = (int) $date_chunks[0];
344 $month = sanitize_text_field( $date_chunks[1] );
345 $dates_number = (int) $date_chunks[4];
346
347 // get previous date chunks
348 $previous_time = strtotime( '-1 months', $time );
349 $previous_date = date( 'Y m W d t', $previous_time );
350 $previous_date_chunks = explode( ' ', $previous_date );
351
352 // get current date
353 $current_date = date_create( 'now', wp_timezone() )->format('Y m W d t');
354 $current_date_chunks = explode( ' ', $current_date );
355
356 // generate dates
357 $data['dates'] = $this->generate_months( $time );
358
359 // generate chart data
360 $sum = [];
361
362 // any post types?
363 if ( ! empty( $post_types ) ) {
364 // reindex post types
365 $post_types = array_combine( range( 1, count( $post_types ) ), array_values( $post_types ) );
366
367 $post_type_data = [];
368
369 foreach ( $post_types as $id => $post_type ) {
370 $post_type_obj = get_post_type_object( $post_type );
371
372 // unrecognized post type? (mainly from deactivated plugins)
373 if ( empty( $post_type_obj ) )
374 $label = $post_type;
375 else
376 $label = $post_type_obj->labels->name;
377
378 $data['data']['datasets'][$id]['label'] = $label;
379 $data['data']['datasets'][$id]['post_type'] = $post_type;
380 $data['data']['datasets'][$id]['hidden'] = in_array( $post_type, $user_options, true );
381 $data['data']['datasets'][$id]['data'] = [];
382
383 // get month views
384 $post_type_data[$id] = array_values(
385 pvc_get_views( apply_filters( 'pvc_dashboard_post_views_query_args',
386 [
387 'fields' => 'date=>views',
388 'post_type' => $post_type,
389 'views_query' => [
390 'year' => $year,
391 'month' => $month,
392 'hide_empty' => true
393 ]
394 ], $period
395 ) )
396 );
397 }
398
399 foreach ( $post_type_data as $post_type_id => $post_views ) {
400 foreach ( $post_views as $id => $views ) {
401 // generate chart data for specific post types
402 $data['data']['datasets'][$post_type_id]['data'][] = $views;
403
404 if ( ! array_key_exists( $id, $sum ) )
405 $sum[$id] = 0;
406
407 $sum[$id] += $views;
408 }
409 }
410 }
411
412 // this month all days
413 for ( $i = 1; $i <= $dates_number; $i++ ) {
414 // generate chart data
415 $data['data']['labels'][] = ( $i % 2 === 0 ? '' : $i );
416 $data['data']['dates'][] = date_i18n( get_option( 'date_format' ), strtotime( $year . '-' . $month . '-' . str_pad( $i, 2, '0', STR_PAD_LEFT ) ) );
417 $data['data']['datasets'][0]['data'][] = ( array_key_exists( $i - 1, $sum ) ? $sum[$i - 1] : 0 );
418 }
419
420 echo wp_json_encode( apply_filters( 'pvc_dashboard_post_views_data', $data, $args ) );
421 exit;
422 }
423
424 /**
425 * Render dashboard widget with most viewed posts.
426 *
427 * @return void
428 */
429 public function dashboard_post_most_viewed() {
430 if ( ! apply_filters( 'pvc_user_can_see_stats', current_user_can( 'publish_posts' ) ) || ! check_ajax_referer( 'pvc-dashboard-widget', 'nonce' ) )
431 wp_die( __( 'You do not have permission to access this page.', 'post-views-counter' ) );
432
433 // get main instance
434 $pvc = Post_Views_Counter();
435
436 // get post types
437 $post_types = Post_Views_Counter()->options['general']['post_types_count'];
438
439 // empty options?
440 if ( empty( $post_types ) || ! is_array( $post_types ) )
441 $post_types = [];
442
443 // sanitize post_types
444 $post_types = map_deep( $post_types, 'sanitize_text_field' );
445
446 // get period
447 $period = isset( $_POST['period'] ) && ! empty( $_POST['period'] ) ? preg_replace( '/[^a-z0-9_|]/', '', $_POST['period'] ) : apply_filters( 'pvc_dashboard_widget_default_period', 'this_month', 'post-most-viewed' );
448
449 // parameters to be used in filter
450 $args = [
451 'widget' => 'post_most_viewed',
452 'period' => $period,
453 'post_types' => $post_types
454 ];
455
456 $data = [
457 'widget' => 'post-most-viewed',
458 'html' => ''
459 ];
460
461 // convert period
462 $time = pvc_period2timestamp( $period );
463
464 // get date chunks
465 $date = date( 'Y m W d t', $time );
466 $date_chunks = explode( ' ', $date );
467
468 // get date
469 $year = (int) $date_chunks[0];
470 $month = sanitize_text_field( $date_chunks[1] );
471
472 // generate dates
473 $data['dates'] = $this->generate_months( $time );
474
475 // query args
476 $query_args = apply_filters( 'pvc_dashboard_post_most_viewed_query_args', [
477 'post_type' => $post_types,
478 'posts_per_page' => 10,
479 'paged' => false,
480 'suppress_filters' => false,
481 'no_found_rows' => true,
482 'views_query' => [
483 'year' => $year,
484 'month' => $month,
485 'hide_empty' => true
486 ]
487 ], $period );
488
489 $posts = pvc_get_most_viewed_posts( $query_args );
490
491 $html = '
492 <table id="pvc-post-most-viewed-table" class="pvc-table pvc-table-hover">
493 <thead>
494 <tr>
495 <th scope="col">#</th>
496 <th scope="col">' . esc_html__( 'Post', 'post-views-counter' ) . '</th>
497 <th scope="col">' . esc_html__( 'Views', 'post-views-counter' ) . '</th>
498 </tr>
499 </thead>
500 <tbody>';
501
502 if ( $posts ) {
503 // active post types
504 $active_post_types = [];
505
506 foreach ( $posts as $index => $post ) {
507 setup_postdata( $post );
508
509 $html .= '
510 <tr>
511 <th scope="col">' . ( $index + 1 ) . '</th>';
512
513 // check post type existence
514 if ( array_key_exists( $post->post_type, $active_post_types ) )
515 $post_type_exists = $active_post_types[$post->post_type];
516 else
517 $post_type_exists = $active_post_types[$post->post_type] = post_type_exists( $post->post_type );
518
519 $title = get_the_title( $post );
520
521 if ( $title === '' )
522 $title = __( '(no title)' );
523
524 // post link
525 $link = '<a href="' . esc_url( get_permalink( $post->ID ) ) . '" target="_blank">' . esc_html( $title ) . '</a>';
526
527 // edit post link
528 if ( $post_type_exists && current_user_can( 'edit_post', $post->ID ) ) {
529 $link .= ' <a href="' . esc_url( get_edit_post_link( $post->ID ) ) . '" class="cn-edit-link" target="_blank">' . esc_html__( 'Edit', 'post-views-counter' ) . '</a>';
530 }
531
532 $html .= '
533 <td>' . $link . '</td>';
534
535 $html .= '
536 <td>' . number_format_i18n( $post->post_views ) . '</td>
537 </tr>';
538 }
539 } else {
540 $html .= '
541 <tr class="no-posts">
542 <td colspan="3">' . esc_html__( 'No most viewed posts found.', 'post-views-counter' ) . '</td>
543 </tr>';
544 }
545
546 $html .= '
547 </tbody>
548 </table>';
549
550 $data['html'] = $html;
551
552 echo wp_json_encode( apply_filters( 'pvc_dashboard_post_most_viewed_data', $data, $args ) );
553 exit;
554 }
555
556 /**
557 * Generate dashboard widget months HTML.
558 *
559 * @param int $timestamp
560 * @return string
561 */
562 public function generate_months( $timestamp, $item = '' ) {
563 $dates = [
564 explode( ' ', date( 'm F Y', strtotime( '-1 months', $timestamp ) ) ),
565 explode( ' ', date( 'm F Y', $timestamp ) ),
566 explode( ' ', date( 'm F Y', strtotime( '+1 months', $timestamp ) ) )
567 ];
568
569 $current = date( 'Ym', current_time( 'timestamp', false ) );
570
571 if ( (int) $current <= (int) ( $dates[1][2] . $dates[1][0] ) )
572 $next = '<span class="next">' . $dates[2][1] . ' ' . $dates[2][2] . ' ›</span>';
573 else
574 $next = '<a class="next" href="#" data-date="' . ( $dates[2][2] . $dates[2][0] ) . '">' . $dates[2][1] . ' ' . $dates[2][2] . ' ›</a>';
575
576 $dates_formatted = apply_filters( 'pvc_dashboard_widget_generate_months_formatted', [
577 'prev' => '<a class="prev" href="#" data-date="' . ( $dates[0][2] . $dates[0][0] ) . '">‹ ' . $dates[0][1] . ' ' . $dates[0][2] . '</a>',
578 'current' => '<span class="current">' . $dates[1][1] . ' ' . $dates[1][2] . '</span>',
579 'next' => $next
580 ], $timestamp, $item );
581
582 return wp_kses_post( apply_filters( 'pvc_dashboard_widget_generate_months_html', $dates_formatted['prev'] . $dates_formatted['current'] . $dates_formatted['next'], $timestamp, $item ) );
583 }
584
585 /**
586 * Update dashboard widget user options.
587 *
588 * @return void
589 */
590 public function update_dashboard_user_options() {
591 if ( ! check_ajax_referer( 'pvc-dashboard-user-options', 'nonce' ) )
592 wp_die( __( 'You do not have permission to access this page.', 'post-views-counter' ) );
593
594 // valid data?
595 if ( isset( $_POST['nonce'], $_POST['options'] ) && ! empty( $_POST['options'] ) ) {
596 // get sanitized options
597 $update = map_deep( $_POST['options'], 'sanitize_text_field' );
598
599 // get user ID
600 $user_id = get_current_user_id();
601
602 // get user dashboard data
603 $user_options = get_user_meta( $user_id, 'pvc_dashboard', true );
604
605 // empty userdata?
606 if ( ! is_array( $user_options ) || empty( $user_options ) )
607 $user_options = [];
608
609 // empty post types?
610 if ( ! array_key_exists( 'post_types', $user_options ) || ! is_array( $user_options['post_types'] ) )
611 $user_options['post_types'] = [];
612
613 // hide post type?
614 if ( ! empty( $update['post_type'] ) ) {
615 // get allowed post types
616 $allowed_post_types = Post_Views_Counter()->options['general']['post_types_count'];
617
618 // simulate total post views as post type
619 $allowed_post_types[] = '_pvc_total_views';
620
621 if ( in_array( $update['post_type'], $allowed_post_types, true ) ) {
622 if ( isset( $update['hidden'] ) && $update['hidden'] === 'true' ) {
623 if ( ! in_array( $update['post_type'], $user_options['post_types'], true ) )
624 $user_options['post_types'][] = $update['post_type'];
625 } else {
626 if ( ( $key = array_search( $update['post_type'], $user_options['post_types'] ) ) !== false )
627 unset( $user_options['post_types'][$key] );
628 }
629 }
630 }
631
632 // empty menu items?
633 if ( ! array_key_exists( 'menu_items', $user_options ) || ! is_array( $user_options['menu_items'] ) )
634 $user_options['menu_items'] = [];
635
636 if ( ! empty( $update['menu_items'] ) && is_array( $update['menu_items'] ) ) {
637 $user_options['menu_items'] = [];
638
639 // get allowed menu items
640 $allowed_menu_items = array_column( $this->widget_items, 'id' );
641
642 foreach ( $update['menu_items'] as $menu_item => $hidden ) {
643 if ( in_array( $menu_item, $allowed_menu_items, true ) && $hidden === 'true' )
644 $user_options['menu_items'][] = $menu_item;
645 }
646 }
647
648 // filter user options
649 $user_options = apply_filters( 'pvc_update_dashboard_user_options', $user_options, $update, $user_id );
650
651 // update userdata
652 update_user_meta( $user_id, 'pvc_dashboard', $user_options );
653
654 echo wp_send_json_success();
655 }
656
657 echo wp_send_json_error();
658 exit;
659 }
660
661 /**
662 * Get user dashboard data.
663 *
664 * @param int $user_id
665 * @param string $data_type
666 * @return array
667 */
668 public function get_dashboard_user_options( $user_id = 0, $data_type = '' ) {
669 $user_options = get_user_meta( $user_id, 'pvc_dashboard', true );
670
671 if ( ! is_array( $user_options ) || empty( $user_options ) )
672 $user_options = [];
673
674 if ( ! array_key_exists( $data_type, $user_options ) || ! is_array( $user_options[$data_type] ) )
675 $user_options[$data_type] = [];
676
677 return $user_options[$data_type];
678 }
679
680 /**
681 * Convert period to timestamp.
682 *
683 * @deprecated
684 * @param string $period
685 * @return int
686 */
687 public function period2timestamp( $period ) {
688 return pvc_period2timestamp( $period );
689 }
690 }
691