PluginProbe ʕ •ᴥ•ʔ
Post Views Counter / 1.5.2
Post Views Counter v1.5.2
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 1 year ago class-columns.php 1 year ago class-counter.php 1 year ago class-crawler-detect.php 1 year ago class-cron.php 1 year ago class-dashboard.php 1 year ago class-frontend.php 1 year ago class-functions.php 1 year ago class-query.php 1 year ago class-settings-api.php 1 year ago class-settings.php 1 year ago class-update.php 1 year ago class-widgets.php 1 year ago functions.php 1 year ago
class-dashboard.php
662 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 Counter', '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.min.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 ];
86
87 wp_add_inline_script( 'pvc-admin-dashboard', 'var pvcArgs = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
88 }
89
90 /**
91 * Setup dashboard widget items.
92 *
93 * @return void
94 */
95 private function setup_widget_items() {
96 // standard items
97 $items = [
98 [
99 'id' => 'post-views',
100 'title' => __( 'Post Views', 'post-views-counter' ),
101 'description' => __( 'Displays a chart of most viewed post types.', 'post-views-counter' ),
102 'content' => '<canvas id="pvc-post-views-chart" height="' . (int) $this->calculate_canvas_size( Post_Views_Counter()->options['general']['post_types_count'] ) . '"></canvas>',
103 'position' => 2
104 ],
105 [
106 'id' => 'post-most-viewed',
107 'title' => __( 'Top Posts', 'post-views-counter' ),
108 'description' => __( 'Displays a list of most viewed single posts or pages.', 'post-views-counter' ),
109 'content' => '<div id="pvc-post-most-viewed-content" class="pvc-table-responsive"></div>',
110 'position' => 3
111 ]
112 ];
113
114 // filter items, do not allow to remove main items
115 $new_items = apply_filters( 'pvc_dashboard_widget_items', [] );
116
117 // any new items?
118 if ( is_array( $new_items ) && ! empty( $new_items ) ) {
119 foreach ( $new_items as $item ) {
120 // add new item
121 array_push( $items, $item );
122 }
123 }
124
125 // sort dashboard items by position
126 array_multisort( array_column( $items, 'position' ), SORT_ASC, SORT_NUMERIC, $items );
127
128 // set widget items
129 $this->widget_items = $items;
130 }
131
132 /**
133 * Calculate canvas height based on number of legend items.
134 *
135 * @param array $data
136 * @param bool $expression
137 * @return int
138 */
139 public function calculate_canvas_size( $data, $expression = true ) {
140 if ( $expression && ! empty( $data ) ) {
141 // treat every 4 legend items as 1 line - 23 pixels
142 $height = 23 * ( (int) ceil( count( $data ) / 4 ) - 1 );
143 } else
144 $height = 0;
145
146 return (int) ( 170 + $height );
147 }
148
149 /**
150 * Render dashboard widget.
151 *
152 * @return void
153 */
154 public function dashboard_widget() {
155 // get user options
156 $user_options = get_user_meta( get_current_user_id(), 'pvc_dashboard', true );
157
158 // empty options?
159 if ( empty( $user_options ) || ! is_array( $user_options ) )
160 $user_options = [];
161
162 // sanitize options
163 $user_options = map_deep( $user_options, 'sanitize_text_field' );
164
165 // get menu items
166 $menu_items = ! empty( $user_options['menu_items'] ) ? $user_options['menu_items'] : [];
167
168 // get widget items
169 $items = $this->widget_items;
170
171 $html = '
172 <div id="pvc-dashboard-accordion" class="pvc-accordion">';
173
174 foreach ( $items as $item ) {
175 $html .= $this->generate_dashboard_widget_item( $item, $menu_items );
176 }
177
178 $html .= '
179 <div class="pvc-dashboard-block"><span>' . esc_html__( 'Powered by', 'post-views-counter' ) . ' <a href="https://postviewscounter.com/?utm_source=post-views-counter-lite&utm_medium=link&utm_campaign=powered-by" target="_blank">Post Views Counter</a></span></div>
180 </div>';
181
182 echo $html;
183 }
184
185 /**
186 * Generate dashboard widget item HTML.
187 *
188 * @param array $item
189 * @param array $menu_items
190 * @param string $dates_html
191 * @return string
192 */
193 public function generate_dashboard_widget_item( $item, $menu_items ) {
194 // get allowed html tags
195 $allowed_html = wp_kses_allowed_html( 'post' );
196 $allowed_html['canvas'] = [
197 'id' => [],
198 'height' => []
199 ];
200
201
202 ob_start(); ?>
203
204 <div id="pvc-<?php esc_attr_e( $item['id'] ); ?>" class="pvc-accordion-item<?php echo ( in_array( $item['id'], $menu_items, true ) ? ' pvc-collapsed' : '' ); ?>">
205 <div class="pvc-accordion-header">
206 <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>
207 <div class="pvc-accordion-actions">
208 <!--<a href="javascript:void(0);" class="pvc-accordion-action dashicons dashicons-admin-generic"></a>-->
209 <a href="javascript:void(0);" class="pvc-accordion-action pvc-toggle-indicator"></a>
210 </div>
211 </div>
212 <div class="pvc-accordion-content">
213 <div class="pvc-dashboard-container loading">
214 <div class="pvc-dashboard-content-top">
215 <?php do_action( 'pvc_dashboard_widget_content_top', $item['id'] ); ?>
216 </div>
217 <div class="pvc-data-container">
218 <?php echo wp_kses( $item['content'], $allowed_html ); ?>
219 <span class="spinner"></span>
220 </div>
221 <div class="pvc-dashboard-content-bottom pvc-date-nav">
222 <div class="pvc-date-nav pvc-months">
223 <?php
224 // generate dates
225 echo wp_kses_post( $this->generate_months( current_time( 'timestamp', false ), $item['id'] ) );
226 ?>
227 </div>
228 <?php do_action( 'pvc_dashboard_widget_content_bottom', $item['id'] ); ?>
229 </div>
230 </div>
231 </div>
232 </div>
233
234 <?php
235 // Output current buffer
236 return ob_get_clean();
237 }
238
239 /**
240 * Render dashboard widget with post views.
241 *
242 * @return void
243 */
244 public function dashboard_post_views_chart() {
245 if ( ! apply_filters( 'pvc_user_can_see_stats', current_user_can( 'publish_posts' ) ) || ! check_ajax_referer( 'pvc-dashboard-widget', 'nonce' ) )
246 wp_die( __( 'You do not have permission to access this page.', 'post-views-counter' ) );
247
248 // get period
249 $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' );
250
251 // get post types
252 $post_types = Post_Views_Counter()->options['general']['post_types_count'];
253
254 // empty options?
255 if ( empty( $post_types ) || ! is_array( $post_types ) )
256 $post_types = [];
257
258 // sanitize post_types
259 $post_types = map_deep( $post_types, 'sanitize_text_field' );
260
261 // get dashboard user options
262 $user_options = $this->get_dashboard_user_options( get_current_user_id(), 'post_types' );
263
264 // empty options?
265 if ( empty( $user_options ) || ! is_array( $user_options ) )
266 $user_options = [];
267
268 // sanitize options
269 $user_options = map_deep( $user_options, 'sanitize_text_field' );
270
271 // get colors
272 $colors = Post_Views_Counter()->functions->get_colors();
273
274 // parameters to be used in filter
275 $args = [
276 'widget' => 'post_views',
277 'period' => $period,
278 'post_types' => $post_types,
279 'user_options' => $user_options
280 ];
281
282 $data = [
283 'widget' => 'post-views',
284 'design' => [
285 'fill' => true,
286 'backgroundColor' => 'rgba(' . $colors['r'] . ',' . $colors['g'] . ',' . $colors['b'] . ', 0.2)',
287 'borderColor' => 'rgba(' . $colors['r'] . ',' . $colors['g'] . ',' . $colors['b'] . ', 1)',
288 'borderWidth' => 1.2,
289 'borderDash' => [],
290 'pointBorderColor' => 'rgba(' . $colors['r'] . ',' . $colors['g'] . ',' . $colors['b'] . ', 1)',
291 'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
292 'pointBorderWidth' => 1.2
293 ],
294 'data' => [
295 'datasets' => [
296 [
297 'label' => __( 'Total Views', 'post-views-counter' ),
298 'post_type' => '_pvc_total_views',
299 'hidden' => in_array( '_pvc_total_views', $user_options, true ),
300 'data' => []
301 ]
302 ]
303 ],
304 ];
305
306 // convert period
307 $time = pvc_period2timestamp( $period );
308
309 // get date chunks
310 $date = date( 'Y m W d t', $time );
311 $date_chunks = explode( ' ', $date );
312
313 // get date
314 $year = (int) $date_chunks[0];
315 $month = sanitize_text_field( $date_chunks[1] );
316 $dates_number = (int) $date_chunks[4];
317
318 // get previous date chunks
319 $previous_time = strtotime( '-1 months', $time );
320 $previous_date = date( 'Y m W d t', $previous_time );
321 $previous_date_chunks = explode( ' ', $previous_date );
322
323 // get current date
324 $current_date = date_create( 'now', wp_timezone() )->format('Y m W d t');
325 $current_date_chunks = explode( ' ', $current_date );
326
327 // generate dates
328 $data['dates'] = $this->generate_months( $time );
329
330 // generate chart data
331 $sum = [];
332
333 // any post types?
334 if ( ! empty( $post_types ) ) {
335 // reindex post types
336 $post_types = array_combine( range( 1, count( $post_types ) ), array_values( $post_types ) );
337
338 $post_type_data = [];
339
340 foreach ( $post_types as $id => $post_type ) {
341 $post_type_obj = get_post_type_object( $post_type );
342
343 // unrecognized post type? (mainly from deactivated plugins)
344 if ( empty( $post_type_obj ) )
345 $label = $post_type;
346 else
347 $label = $post_type_obj->labels->name;
348
349 $data['data']['datasets'][$id]['label'] = $label;
350 $data['data']['datasets'][$id]['post_type'] = $post_type;
351 $data['data']['datasets'][$id]['hidden'] = in_array( $post_type, $user_options, true );
352 $data['data']['datasets'][$id]['data'] = [];
353
354 // get month views
355 $post_type_data[$id] = array_values(
356 pvc_get_views( apply_filters( 'pvc_dashboard_post_views_query_args',
357 [
358 'fields' => 'date=>views',
359 'post_type' => $post_type,
360 'views_query' => [
361 'year' => $year,
362 'month' => $month,
363 'hide_empty' => true
364 ]
365 ], $period
366 ) )
367 );
368 }
369
370 foreach ( $post_type_data as $post_type_id => $post_views ) {
371 foreach ( $post_views as $id => $views ) {
372 // generate chart data for specific post types
373 $data['data']['datasets'][$post_type_id]['data'][] = $views;
374
375 if ( ! array_key_exists( $id, $sum ) )
376 $sum[$id] = 0;
377
378 $sum[$id] += $views;
379 }
380 }
381 }
382
383 // this month all days
384 for ( $i = 1; $i <= $dates_number; $i++ ) {
385 // generate chart data
386 $data['data']['labels'][] = ( $i % 2 === 0 ? '' : $i );
387 $data['data']['dates'][] = date_i18n( get_option( 'date_format' ), strtotime( $year . '-' . $month . '-' . str_pad( $i, 2, '0', STR_PAD_LEFT ) ) );
388 $data['data']['datasets'][0]['data'][] = ( array_key_exists( $i - 1, $sum ) ? $sum[$i - 1] : 0 );
389 }
390
391 echo wp_json_encode( apply_filters( 'pvc_dashboard_post_views_data', $data, $args ) );
392 exit;
393 }
394
395 /**
396 * Render dashboard widget with most viewed posts.
397 *
398 * @return void
399 */
400 public function dashboard_post_most_viewed() {
401 if ( ! apply_filters( 'pvc_user_can_see_stats', current_user_can( 'publish_posts' ) ) || ! check_ajax_referer( 'pvc-dashboard-widget', 'nonce' ) )
402 wp_die( __( 'You do not have permission to access this page.', 'post-views-counter' ) );
403
404 // get main instance
405 $pvc = Post_Views_Counter();
406
407 // get post types
408 $post_types = Post_Views_Counter()->options['general']['post_types_count'];
409
410 // empty options?
411 if ( empty( $post_types ) || ! is_array( $post_types ) )
412 $post_types = [];
413
414 // sanitize post_types
415 $post_types = map_deep( $post_types, 'sanitize_text_field' );
416
417 // get period
418 $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' );
419
420 // parameters to be used in filter
421 $args = [
422 'widget' => 'post_most_viewed',
423 'period' => $period,
424 'post_types' => $post_types
425 ];
426
427 $data = [
428 'widget' => 'post-most-viewed',
429 'html' => ''
430 ];
431
432 // convert period
433 $time = pvc_period2timestamp( $period );
434
435 // get date chunks
436 $date = date( 'Y m W d t', $time );
437 $date_chunks = explode( ' ', $date );
438
439 // get date
440 $year = (int) $date_chunks[0];
441 $month = sanitize_text_field( $date_chunks[1] );
442
443 // generate dates
444 $data['dates'] = $this->generate_months( $time );
445
446 // query args
447 $query_args = apply_filters( 'pvc_dashboard_post_most_viewed_query_args', [
448 'post_type' => $post_types,
449 'posts_per_page' => 10,
450 'paged' => false,
451 'suppress_filters' => false,
452 'no_found_rows' => true,
453 'views_query' => [
454 'year' => $year,
455 'month' => $month,
456 'hide_empty' => true
457 ]
458 ], $period );
459
460 $posts = pvc_get_most_viewed_posts( $query_args );
461
462 $html = '
463 <table id="pvc-post-most-viewed-table" class="pvc-table pvc-table-hover">
464 <thead>
465 <tr>
466 <th scope="col">#</th>
467 <th scope="col">' . esc_html__( 'Post', 'post-views-counter' ) . '</th>
468 <th scope="col">' . esc_html__( 'Views', 'post-views-counter' ) . '</th>
469 </tr>
470 </thead>
471 <tbody>';
472
473 if ( $posts ) {
474 // active post types
475 $active_post_types = [];
476
477 foreach ( $posts as $index => $post ) {
478 setup_postdata( $post );
479
480 $html .= '
481 <tr>
482 <th scope="col">' . ( $index + 1 ) . '</th>';
483
484 // check post type existence
485 if ( array_key_exists( $post->post_type, $active_post_types ) )
486 $post_type_exists = $active_post_types[$post->post_type];
487 else
488 $post_type_exists = $active_post_types[$post->post_type] = post_type_exists( $post->post_type );
489
490 $title = get_the_title( $post );
491
492 if ( $title === '' )
493 $title = __( '(no title)' );
494
495 // post link
496 $link = '<a href="' . esc_url( get_permalink( $post->ID ) ) . '" target="_blank">' . esc_html( $title ) . '</a>';
497
498 // edit post link
499 if ( $post_type_exists && current_user_can( 'edit_post', $post->ID ) ) {
500 $link .= ' <a href="' . esc_url( get_edit_post_link( $post->ID ) ) . '" class="cn-edit-link" target="_blank">' . esc_html__( 'Edit', 'post-views-counter' ) . '</a>';
501 }
502
503 $html .= '
504 <td>' . $link . '</td>';
505
506 $html .= '
507 <td>' . number_format_i18n( $post->post_views ) . '</td>
508 </tr>';
509 }
510 } else {
511 $html .= '
512 <tr class="no-posts">
513 <td colspan="3">' . esc_html__( 'No most viewed posts found.', 'post-views-counter' ) . '</td>
514 </tr>';
515 }
516
517 $html .= '
518 </tbody>
519 </table>';
520
521 $data['html'] = $html;
522
523 echo wp_json_encode( apply_filters( 'pvc_dashboard_post_most_viewed_data', $data, $args ) );
524 exit;
525 }
526
527 /**
528 * Generate dashboard widget months HTML.
529 *
530 * @param int $timestamp
531 * @return string
532 */
533 public function generate_months( $timestamp, $item = '' ) {
534 $dates = [
535 explode( ' ', date( 'm F Y', strtotime( '-1 months', $timestamp ) ) ),
536 explode( ' ', date( 'm F Y', $timestamp ) ),
537 explode( ' ', date( 'm F Y', strtotime( '+1 months', $timestamp ) ) )
538 ];
539
540 $current = date( 'Ym', current_time( 'timestamp', false ) );
541
542 if ( (int) $current <= (int) ( $dates[1][2] . $dates[1][0] ) )
543 $next = '<span class="next">' . $dates[2][1] . ' ' . $dates[2][2] . ' ›</span>';
544 else
545 $next = '<a class="next" href="#" data-date="' . ( $dates[2][2] . $dates[2][0] ) . '">' . $dates[2][1] . ' ' . $dates[2][2] . ' ›</a>';
546
547 $dates_formatted = apply_filters( 'pvc_dashboard_widget_generate_months_formatted', [
548 'prev' => '<a class="prev" href="#" data-date="' . ( $dates[0][2] . $dates[0][0] ) . '">‹ ' . $dates[0][1] . ' ' . $dates[0][2] . '</a>',
549 'current' => '<span class="current">' . $dates[1][1] . ' ' . $dates[1][2] . '</span>',
550 'next' => $next
551 ], $timestamp, $item );
552
553 return wp_kses_post( apply_filters( 'pvc_dashboard_widget_generate_months_html', $dates_formatted['prev'] . $dates_formatted['current'] . $dates_formatted['next'], $timestamp, $item ) );
554 }
555
556 /**
557 * Update dashboard widget user options.
558 *
559 * @return void
560 */
561 public function update_dashboard_user_options() {
562 if ( ! check_ajax_referer( 'pvc-dashboard-user-options', 'nonce' ) )
563 wp_die( __( 'You do not have permission to access this page.', 'post-views-counter' ) );
564
565 // valid data?
566 if ( isset( $_POST['nonce'], $_POST['options'] ) && ! empty( $_POST['options'] ) ) {
567 // get sanitized options
568 $update = map_deep( $_POST['options'], 'sanitize_text_field' );
569
570 // get user ID
571 $user_id = get_current_user_id();
572
573 // get user dashboard data
574 $user_options = get_user_meta( $user_id, 'pvc_dashboard', true );
575
576 // empty userdata?
577 if ( ! is_array( $user_options ) || empty( $user_options ) )
578 $user_options = [];
579
580 // empty post types?
581 if ( ! array_key_exists( 'post_types', $user_options ) || ! is_array( $user_options['post_types'] ) )
582 $user_options['post_types'] = [];
583
584 // hide post type?
585 if ( ! empty( $update['post_type'] ) ) {
586 // get allowed post types
587 $allowed_post_types = Post_Views_Counter()->options['general']['post_types_count'];
588
589 // simulate total post views as post type
590 $allowed_post_types[] = '_pvc_total_views';
591
592 if ( in_array( $update['post_type'], $allowed_post_types, true ) ) {
593 if ( isset( $update['hidden'] ) && $update['hidden'] === 'true' ) {
594 if ( ! in_array( $update['post_type'], $user_options['post_types'], true ) )
595 $user_options['post_types'][] = $update['post_type'];
596 } else {
597 if ( ( $key = array_search( $update['post_type'], $user_options['post_types'] ) ) !== false )
598 unset( $user_options['post_types'][$key] );
599 }
600 }
601 }
602
603 // empty menu items?
604 if ( ! array_key_exists( 'menu_items', $user_options ) || ! is_array( $user_options['menu_items'] ) )
605 $user_options['menu_items'] = [];
606
607 if ( ! empty( $update['menu_items'] ) && is_array( $update['menu_items'] ) ) {
608 $user_options['menu_items'] = [];
609
610 // get allowed menu items
611 $allowed_menu_items = array_column( $this->widget_items, 'id' );
612
613 foreach ( $update['menu_items'] as $menu_item => $hidden ) {
614 if ( in_array( $menu_item, $allowed_menu_items, true ) && $hidden === 'true' )
615 $user_options['menu_items'][] = $menu_item;
616 }
617 }
618
619 // filter user options
620 $user_options = apply_filters( 'pvc_update_dashboard_user_options', $user_options, $update, $user_id );
621
622 // update userdata
623 update_user_meta( $user_id, 'pvc_dashboard', $user_options );
624
625 echo wp_send_json_success();
626 }
627
628 echo wp_send_json_error();
629 exit;
630 }
631
632 /**
633 * Get user dashboard data.
634 *
635 * @param int $user_id
636 * @param string $data_type
637 * @return array
638 */
639 public function get_dashboard_user_options( $user_id = 0, $data_type = '' ) {
640 $user_options = get_user_meta( $user_id, 'pvc_dashboard', true );
641
642 if ( ! is_array( $user_options ) || empty( $user_options ) )
643 $user_options = [];
644
645 if ( ! array_key_exists( $data_type, $user_options ) || ! is_array( $user_options[$data_type] ) )
646 $user_options[$data_type] = [];
647
648 return $user_options[$data_type];
649 }
650
651 /**
652 * Convert period to timestamp.
653 *
654 * @deprecated
655 * @param string $period
656 * @return int
657 */
658 public function period2timestamp( $period ) {
659 return pvc_period2timestamp( $period );
660 }
661
662 }