PluginProbe
WebberZone Top 10 — Popular Posts / 4.3.1
WebberZone Top 10 — Popular Posts v4.3.1
4.5.1 4.5.0 4.4.3 4.4.2 4.4.1 4.4.0 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 trunk 1.0 1.0.1 1.1 1.2 1.3 1.4 1.4.1 1.5 1.5.1 1.5.2 1.5.3 1.6 1.6.1 All 117 releases
top-10 / includes / admin / class-dashboard.php

class-dashboard.php in WebberZone Top 10 — Popular Posts 4.3.1, at includes/admin/class-dashboard.php

743 lines 24.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Dashboard class.
4 *
5 * @package WebberZone\Top_Ten\Admin
6 */
7
8 namespace WebberZone\Top_Ten\Admin;
9
10 use WebberZone\Top_Ten\Admin\Settings\Settings_API;
11 use WebberZone\Top_Ten\Database;
12
13 if ( ! defined( 'WPINC' ) ) {
14 die;
15 }
16
17 /**
18 * Admin Dashboard Class.
19 *
20 * @since 3.0.0
21 */
22 class Dashboard {
23
24 /**
25 * Parent Menu ID.
26 *
27 * @since 3.0.0
28 *
29 * @var string Parent Menu ID.
30 */
31 public $parent_id;
32
33 /**
34 * Constructor class.
35 *
36 * @since 3.0.0
37 */
38 public function __construct() {
39 add_action( 'admin_menu', array( $this, 'admin_menu' ) );
40 add_action( 'network_admin_menu', array( $this, 'network_admin_menu' ), 9 );
41 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
42 add_action( 'wp_ajax_tptn_chart_data', array( $this, 'get_chart_data' ) );
43 }
44
45 /**
46 * Render the settings page.
47 *
48 * @since 3.0.0
49 */
50 public function render_page() {
51 ob_start();
52
53 // Add date selector.
54 $chart_to_date = current_time( 'd M Y' );
55 $chart_from_date = gmdate( 'd M Y', strtotime( '-1 month' ) );
56
57 $post_date_from = ( isset( $_REQUEST['post-date-filter-from'] ) && check_admin_referer( 'tptn-dashboard' ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['post-date-filter-from'] ) ) : $chart_from_date;
58
59 $post_date_to = ( isset( $_REQUEST['post-date-filter-to'] ) && check_admin_referer( 'tptn-dashboard' ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['post-date-filter-to'] ) ) : $chart_to_date;
60
61 ?>
62 <div class="wrap">
63 <h1><?php esc_html_e( 'Top 10 Dashboard', 'top-10' ); ?></h1>
64 <?php do_action( 'tptn_settings_page_header' ); ?>
65
66 <?php settings_errors(); ?>
67
68 <div id="poststuff">
69 <div id="post-body" class="metabox-holder columns-2">
70 <div id="post-body-content">
71 <form method="post" >
72 <?php wp_nonce_field( 'tptn-dashboard' ); ?>
73
74 <div>
75 <input type="text" id="datepicker-from" name="post-date-filter-from" value="<?php echo esc_attr( $post_date_from ); ?>" size="11" />
76 <input type="text" id="datepicker-to" name="post-date-filter-to" value="<?php echo esc_attr( $post_date_to ); ?>" size="11" />
77 <?php
78 submit_button(
79 __( 'Update', 'top-10' ),
80 'primary',
81 'filter_action',
82 false,
83 array(
84 'id' => 'top-10-chart-submit',
85 'onclick' => 'updateChart(); return false;',
86 )
87 );
88 ?>
89 </div>
90 <div>
91 <canvas id="visits" width="400" height="150" aria-label="<?php esc_html_e( 'Top 10 Visits', 'top-10' ); ?>" role="img"></canvas>
92 </div>
93
94 </form>
95
96 <h2><?php esc_html_e( 'Historical visits', 'top-10' ); ?></h2>
97 <div id="dashboard-historical-visits">
98 <ul class="nav-tab-wrapper" style="padding:0; border-bottom: 1px solid #ccc;">
99 <?php
100 foreach ( $this->get_tabs() as $tab_id => $tab_name ) {
101 $tab_class = 'nav-tab';
102 $tab_style = '';
103
104 // Check if this tab should be hidden initially.
105 if ( isset( $tab_name['hide'] ) && $tab_name['hide'] ) {
106 $tab_style = 'display:none;';
107 }
108
109 // Add custom class if specified.
110 if ( isset( $tab_name['class'] ) ) {
111 $tab_class .= ' ' . $tab_name['class'];
112 }
113
114 echo '<li style="padding:0; border:0; margin:0;"><a href="#' . esc_attr( $tab_id ) . '" title="' . esc_attr( $tab_name['title'] ) . '" class="' . esc_attr( $tab_class ) . '" style="' . esc_attr( $tab_style ) . '">';
115 echo esc_html( $tab_name['title'] );
116 echo '</a></li>';
117
118 }
119 ?>
120 </ul>
121
122 <form method="post" action="options.php">
123
124 <?php foreach ( $this->get_tabs() as $tab_id => $tab_name ) : ?>
125
126 <div id="<?php echo esc_attr( $tab_id ); ?>">
127 <?php
128 $output = empty( $tab_name['hide'] ) ? $this->display_popular_posts( $tab_name ) : '';
129 echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
130 ?>
131
132 <div style="font-weight:bold;padding:5px;">
133
134 <?php
135 $query_args = array(
136 'order' => 'desc',
137 );
138 $daily = ( isset( $tab_name['daily'] ) ) ? $tab_name['daily'] : true;
139
140 if ( $daily ) {
141 $query_args['orderby'] = 'daily_count';
142
143 if ( ! empty( $tab_name['from_date'] ) ) {
144 $query_args['post-date-filter-from'] = gmdate( 'd+M+Y', strtotime( $tab_name['from_date'] ) );
145 }
146 if ( ! empty( $tab_name['to_date'] ) ) {
147 $query_args['post-date-filter-to'] = gmdate( 'd+M+Y', strtotime( $tab_name['to_date'] ) );
148 }
149 } else {
150 $query_args['orderby'] = 'total_count';
151 }
152 $base_url = is_network_admin() ? network_admin_url( 'admin.php?page=tptn_network_pop_posts_page' ) : admin_url( 'admin.php?page=tptn_popular_posts' );
153 $url = add_query_arg( $query_args, $base_url );
154
155 ?>
156
157 <a href="<?php echo esc_url( $url ); ?>"><?php esc_html_e( 'View all popular posts', 'top-10' ); ?> &raquo;</a>
158
159 </div>
160
161 </div><!-- /#tab_id-->
162
163 <?php endforeach; ?>
164
165 </form>
166 </div>
167
168 </div><!-- /#post-body-content -->
169
170 <div id="postbox-container-1" class="postbox-container">
171
172 <div id="side-sortables" class="meta-box-sortables ui-sortable">
173 <?php include_once 'sidebar.php'; ?>
174 </div><!-- /#side-sortables -->
175
176 </div><!-- /#postbox-container-1 -->
177 </div><!-- /#post-body -->
178 <br class="clear" />
179 </div><!-- /#poststuff -->
180
181 </div><!-- /.wrap -->
182
183 <?php
184 echo ob_get_clean(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
185 }
186
187 /**
188 * Admin Menu.
189 *
190 * @since 3.0.0
191 */
192 public function admin_menu() {
193 $roles = wp_parse_list( \tptn_get_option( 'show_dashboard_to_roles' ) );
194
195 $this->parent_id = add_menu_page(
196 esc_html__( 'Top 10 Dashboard', 'top-10' ),
197 esc_html__( 'Top 10', 'top-10' ),
198 Settings_API::get_capability_for_menu( $roles ),
199 'tptn_dashboard',
200 array( $this, 'render_page' ),
201 'dashicons-editor-ol'
202 );
203
204 add_submenu_page(
205 'tptn_dashboard',
206 esc_html__( 'Top 10 Dashboard', 'top-10' ),
207 esc_html__( 'Dashboard', 'top-10' ),
208 Settings_API::get_capability_for_menu( $roles ),
209 'tptn_dashboard',
210 array( $this, 'render_page' )
211 );
212
213 add_action( 'load-' . $this->parent_id, array( $this, 'help_tabs' ) );
214 }
215
216 /**
217 * Network Admin Menu.
218 *
219 * @since 4.2.0
220 */
221 public function network_admin_menu() {
222 $this->parent_id = add_menu_page(
223 esc_html__( 'Top 10 Dashboard', 'top-10' ),
224 esc_html__( 'Top 10', 'top-10' ),
225 'manage_network_options',
226 'tptn_dashboard',
227 array( $this, 'render_page' ),
228 'dashicons-editor-ol'
229 );
230
231 add_submenu_page(
232 'tptn_dashboard',
233 esc_html__( 'Top 10 Dashboard', 'top-10' ),
234 esc_html__( 'Dashboard', 'top-10' ),
235 'manage_network_options',
236 'tptn_dashboard',
237 array( $this, 'render_page' )
238 );
239
240 add_action( 'load-' . $this->parent_id, array( $this, 'help_tabs' ) );
241 }
242
243 /**
244 * Enqueue scripts in admin area.
245 *
246 * @since 3.0.0
247 *
248 * @param string $hook The current admin page.
249 */
250 public function admin_enqueue_scripts( $hook ) {
251
252 if ( $hook === $this->parent_id ) {
253 wp_enqueue_script( 'moment' );
254 wp_enqueue_script( 'top-ten-chart-js' );
255 wp_enqueue_script( 'top-ten-chart-datalabels-js' );
256 wp_enqueue_script( 'top-ten-chartjs-adapter-luxon-js' );
257 wp_enqueue_script( 'top-ten-chart-data-js' );
258 wp_enqueue_script( 'top-ten-admin-js' );
259
260 $enable_bar_click = function_exists( '\\WebberZone\\Top_Ten\\tptn_freemius' ) && \WebberZone\Top_Ten\tptn_freemius()->can_use_premium_code();
261
262 $stats_base_url = is_network_admin()
263 ? network_admin_url( 'admin.php?page=tptn_network_pop_posts_page' )
264 : admin_url( 'admin.php?page=tptn_popular_posts' );
265
266 wp_localize_script(
267 'top-ten-chart-data-js',
268 'tptn_chart_data',
269 array(
270 'security' => wp_create_nonce( 'tptn-dashboard' ),
271 'datasetlabel' => __( 'Visits', 'top-10' ),
272 'charttitle' => __( 'Daily Visits', 'top-10' ),
273 'network' => is_network_admin() ? 1 : 0,
274 'enableBarClick' => $enable_bar_click ? 1 : 0,
275 'statsUrl' => $stats_base_url,
276 'clickBarHint' => __( 'Click to view top posts for this day', 'top-10' ),
277 )
278 );
279 wp_enqueue_style( 'top-ten-admin-css' );
280 }
281 }
282
283 /**
284 * Fetch chart data for visits over time.
285 *
286 * @since 4.2.0
287 *
288 * @param string $from_date Start date in Y-m-d format.
289 * @param string $to_date End date in Y-m-d format.
290 * @param bool $network Whether to fetch network-wide data.
291 * @return array Chart data with date and visits.
292 */
293 public static function fetch_visits_by_date( $from_date, $to_date, $network = false ) {
294 global $wpdb;
295
296 if ( $network ) {
297 $sql = $wpdb->prepare(
298 " SELECT SUM(cntaccess) AS visits, DATE(dp_date) as date
299 FROM {$wpdb->base_prefix}top_ten_daily
300 WHERE DATE(dp_date) >= DATE(%s)
301 AND DATE(dp_date) <= DATE(%s)
302 GROUP BY date
303 ORDER BY date ASC
304 ",
305 $from_date,
306 $to_date
307 );
308 } else {
309 $blog_id = get_current_blog_id();
310
311 $sql = $wpdb->prepare(
312 " SELECT SUM(cntaccess) AS visits, DATE(dp_date) as date
313 FROM {$wpdb->base_prefix}top_ten_daily
314 WHERE DATE(dp_date) >= DATE(%s)
315 AND DATE(dp_date) <= DATE(%s)
316 AND blog_id = %d
317 GROUP BY date
318 ORDER BY date ASC
319 ",
320 $from_date,
321 $to_date,
322 $blog_id
323 );
324 }
325
326 $result = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
327
328 $data = array();
329 foreach ( $result as $row ) {
330 $data[] = $row;
331 }
332
333 return $data;
334 }
335
336 /**
337 * Function to add an action to search for tags using Ajax.
338 *
339 * @since 3.0.0
340 */
341 public function get_chart_data() {
342 $roles = wp_parse_list( \tptn_get_option( 'show_dashboard_to_roles' ) );
343
344 if ( ! current_user_can( Settings_API::get_capability_for_menu( $roles ) ) ) {
345 wp_die();
346 }
347 check_ajax_referer( 'tptn-dashboard', 'security' );
348
349 // Add date selector.
350 $to_date = isset( $_REQUEST['to_date'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['to_date'] ) ) : current_time( 'd M Y' );
351 $from_date = isset( $_REQUEST['from_date'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['from_date'] ) ) : gmdate( 'd M Y', strtotime( '-1 month' ) );
352
353 $post_date_from = gmdate( 'Y-m-d', strtotime( $from_date ) );
354 $post_date_to = gmdate( 'Y-m-d', strtotime( $to_date ) );
355
356 $network_request = is_multisite() && isset( $_REQUEST['network'] ) && 1 === (int) $_REQUEST['network'];
357
358 $data = self::fetch_visits_by_date( $post_date_from, $post_date_to, $network_request );
359
360 echo wp_json_encode( $data );
361 wp_die();
362 }
363
364
365 /**
366 * Array containing the settings' sections.
367 *
368 * @since 3.0.0
369 *
370 * @return array Settings array
371 */
372 public function get_tabs() {
373 $tabs = array(
374 'today' => array(
375 'title' => __( 'Today', 'top-10' ),
376 'from_date' => current_time( 'd M Y' ),
377 'to_date' => current_time( 'd M Y' ),
378 ),
379 'yesterday' => array(
380 'title' => __( 'Yesterday', 'top-10' ),
381 'from_date' => gmdate( 'd M Y', strtotime( '-1 day' ) ),
382 'to_date' => gmdate( 'd M Y', strtotime( '-1 day' ) ),
383 ),
384 'lastweek' => array(
385 'title' => __( 'Last 7 days', 'top-10' ),
386 'from_date' => gmdate( 'd M Y', strtotime( '-1 week' ) ),
387 'to_date' => current_time( 'd M Y' ),
388 ),
389 'lastfortnight' => array(
390 'title' => __( 'Last 14 days', 'top-10' ),
391 'from_date' => gmdate( 'd M Y', strtotime( '-2 weeks' ) ),
392 'to_date' => current_time( 'd M Y' ),
393 ),
394 'lastmonth' => array(
395 'title' => __( 'Last 30 days', 'top-10' ),
396 'from_date' => gmdate( 'd M Y', strtotime( '-30 days' ) ),
397 'to_date' => current_time( 'd M Y' ),
398 ),
399 'overall' => array(
400 'title' => __( 'All time', 'top-10' ),
401 'daily' => false,
402 ),
403 );
404
405 /**
406 * Filters the tabs for the admin dashboard.
407 *
408 * @since 4.1.0
409 *
410 * @param array $tabs Array of tabs.
411 */
412 $tabs = apply_filters( 'tptn_admin_dashboard_tabs', $tabs );
413
414 return $tabs;
415 }
416
417 /**
418 * Get popular posts for a date range.
419 *
420 * @since 3.0.0
421 *
422 * @param string|array $args {
423 * Optional. Array or string of Query parameters.
424 *
425 * @type bool $daily Set to true to get the daily/custom period posts. False for overall.
426 * @type string $from_date From date. A date/time string.
427 * @type int $numberposts Number of posts to fetch.
428 * @type string $to_date To date. A date/time string.
429 * }
430 * @return string HTML table with popular posts.
431 */
432 public function display_popular_posts( $args = array() ) {
433 $output = '';
434
435 $defaults = array(
436 'daily' => true,
437 'from_date' => null,
438 'numberposts' => 20,
439 'to_date' => null,
440 );
441 $args = wp_parse_args( $args, $defaults );
442
443 $results = $this->get_popular_posts( $args );
444
445 ob_start();
446 $explicit_network = isset( $args['network'] ) ? (bool) $args['network'] : null;
447 $is_network = ( null !== $explicit_network ) ? $explicit_network : ( is_multisite() && is_network_admin() );
448 if ( $results ) :
449 ?>
450
451 <table class="widefat striped">
452 <thead>
453 <tr>
454 <th><?php esc_html_e( 'Post', 'top-10' ); ?></th>
455 <?php if ( $is_network ) : ?>
456 <th><?php esc_html_e( 'Site', 'top-10' ); ?></th>
457 <?php endif; ?>
458 <th style="text-align:center;"><?php esc_html_e( 'Visits', 'top-10' ); ?></th>
459 </tr>
460 </thead>
461 <tbody>
462 <?php
463 foreach ( $results as $result ) :
464 $visits_int = (int) $result['visits'];
465 $visits = \WebberZone\Top_Ten\Util\Helpers::number_format_i18n( $visits_int );
466 if ( $is_network && isset( $result['blog_id'] ) ) {
467 $post = get_blog_post( (int) $result['blog_id'], (int) $result['ID'] );
468 $permalink = is_multisite() ? get_blog_permalink( (int) $result['blog_id'], (int) $result['ID'] ) : get_permalink( (int) $result['ID'] );
469 } else {
470 $post = get_post( (int) $result['ID'] );
471 $permalink = get_permalink( (int) $result['ID'] );
472 }
473 if ( ! $post ) {
474 continue;
475 }
476 ?>
477 <tr>
478 <td><a href="<?php echo esc_url( $permalink ); ?>" target="_blank"><?php echo esc_html( get_the_title( $post ) ); ?></a></td>
479 <?php if ( $is_network && isset( $result['blog_id'] ) ) : ?>
480 <td>
481 <?php
482 $blog_details = get_blog_details( (int) $result['blog_id'] );
483 if ( $blog_details ) {
484 $site_url = add_query_arg(
485 array(
486 'page' => 'tptn_popular_posts',
487 ),
488 get_admin_url( (int) $result['blog_id'], 'admin.php' )
489 );
490 ?>
491 <a href="<?php echo esc_url( $site_url ); ?>" target="_blank"><?php echo esc_html( $blog_details->blogname ); ?></a>
492 <?php
493 } else {
494 /* translators: %d is the blog ID */
495 echo esc_html( sprintf( __( 'Blog ID: %d', 'top-10' ), (int) $result['blog_id'] ) );
496 }
497 ?>
498 </td>
499 <?php endif; ?>
500 <td style="text-align:center;"><?php echo esc_html( $visits ); ?></td>
501 </tr>
502
503 <?php endforeach; ?>
504 </tbody>
505 <?php
506 $colspan = $is_network ? 2 : 1;
507 $total_visits_formatted = \WebberZone\Top_Ten\Util\Helpers::number_format_i18n( $this->get_period_total_visits( $args ) );
508 $label = $is_network ? __( 'Total network visits for this period', 'top-10' ) : __( 'Total visits for this period', 'top-10' );
509 ?>
510 <tfoot>
511 <tr>
512 <th colspan="<?php echo esc_attr( (string) $colspan ); ?>" style="text-align:right;"><?php echo esc_html( $label ); ?></th>
513 <th style="text-align:center;"><?php echo esc_html( $total_visits_formatted ); ?></th>
514 </tr>
515 </tfoot>
516 </table>
517
518 <?php else : ?>
519
520 <?php esc_html_e( 'Sorry, no popular posts found.', 'top-10' ); ?>
521
522 <?php endif; ?>
523
524 <?php
525
526 $output = ob_get_clean();
527 return $output;
528 }
529
530 /**
531 * Get the raw total visits for a period, matching the chart methodology.
532 *
533 * @since 4.3.0
534 *
535 * @param array $args Query parameters (daily, from_date, to_date, blog_id, network).
536 * @return int Total visits.
537 */
538 public function get_period_total_visits( $args = array() ) {
539 global $wpdb;
540
541 $defaults = array(
542 'blog_id' => get_current_blog_id(),
543 'daily' => true,
544 'from_date' => null,
545 'to_date' => null,
546 );
547 $args = wp_parse_args( $args, $defaults );
548
549 $explicit_network = isset( $args['network'] ) ? (bool) $args['network'] : null;
550 $is_network = ( null !== $explicit_network ) ? $explicit_network : ( is_multisite() && is_network_admin() );
551 $table_name = Database::get_table( $args['daily'] );
552
553 $has_dates = ! empty( $args['from_date'] ) && ! empty( $args['to_date'] );
554
555 if ( $args['daily'] && $has_dates && $is_network ) {
556 $from_date = gmdate( 'Y-m-d', strtotime( $args['from_date'] ) );
557 $to_date = gmdate( 'Y-m-d', strtotime( $args['to_date'] ) );
558 $sql = $wpdb->prepare(
559 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
560 "SELECT SUM(cntaccess) FROM {$table_name} WHERE DATE(dp_date) >= DATE(%s) AND DATE(dp_date) <= DATE(%s)",
561 $from_date,
562 $to_date
563 );
564 } elseif ( $args['daily'] && $has_dates ) {
565 $blog_id = (int) $args['blog_id'];
566 $from_date = gmdate( 'Y-m-d', strtotime( $args['from_date'] ) );
567 $to_date = gmdate( 'Y-m-d', strtotime( $args['to_date'] ) );
568 $sql = $wpdb->prepare(
569 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
570 "SELECT SUM(cntaccess) FROM {$table_name} WHERE DATE(dp_date) >= DATE(%s) AND DATE(dp_date) <= DATE(%s) AND blog_id = %d",
571 $from_date,
572 $to_date,
573 $blog_id
574 );
575 } elseif ( $is_network ) {
576 $sql = "SELECT SUM(cntaccess) FROM {$table_name}"; // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
577 } else {
578 $blog_id = (int) $args['blog_id'];
579 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
580 $sql = $wpdb->prepare( "SELECT SUM(cntaccess) FROM {$table_name} WHERE blog_id = %d", $blog_id );
581 }
582
583 $total = $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
584
585 return (int) $total;
586 }
587
588 /**
589 * Retrieve the popular posts.
590 *
591 * @since 3.0.0
592 *
593 * @param string|array $args {
594 * Optional. Array or string of Query parameters.
595 *
596 * @type array|string $blog_id An array or comma-separated string of blog IDs.
597 * @type bool $daily Set to true to get the daily/custom period posts. False for overall.
598 * @type string $from_date From date. A date/time string.
599 * @type int $numberposts Number of posts to fetch.
600 * @type int $offset Offset.
601 * @type string $to_date To date. A date/time string.
602 * }
603 * @return array Array of post objects.
604 */
605 public function get_popular_posts( $args = array() ) {
606 global $wpdb;
607
608 // Initialise some variables.
609 $fields = array();
610 $where = '';
611 $join = '';
612 $groupby = '';
613 $orderby = '';
614 $limits = '';
615
616 $defaults = array(
617 'blog_id' => get_current_blog_id(),
618 'daily' => true,
619 'from_date' => null,
620 'numberposts' => 20,
621 'offset' => 0,
622 'to_date' => null,
623 );
624 $args = wp_parse_args( $args, $defaults );
625
626 $explicit_network = isset( $args['network'] ) ? (bool) $args['network'] : null;
627 $is_network = ( null !== $explicit_network ) ? $explicit_network : ( is_multisite() && is_network_admin() );
628 $table_name = Database::get_table( $args['daily'] );
629
630 if ( $is_network ) {
631 // Network-wide: aggregate across all blogs.
632 $fields[] = ( $args['daily'] ) ? "SUM({$table_name}.cntaccess) as visits" : "{$table_name}.cntaccess as visits";
633 $fields[] = "{$table_name}.postnumber as ID";
634 $fields[] = "{$table_name}.blog_id as blog_id";
635
636 $fields = implode( ', ', $fields );
637
638 $where = ' 1=1 ';
639
640 if ( isset( $args['from_date'] ) && ! empty( $args['from_date'] ) && $args['daily'] ) {
641 $from_date = gmdate( 'Y-m-d', strtotime( $args['from_date'] ) );
642 $where .= $wpdb->prepare( " AND DATE({$table_name}.dp_date) >= DATE(%s) ", $from_date ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
643 }
644
645 if ( isset( $args['to_date'] ) && ! empty( $args['to_date'] ) && $args['daily'] ) {
646 $to_date = gmdate( 'Y-m-d', strtotime( $args['to_date'] ) );
647 $where .= $wpdb->prepare( " AND DATE({$table_name}.dp_date) <= DATE(%s) ", $to_date ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
648 }
649
650 $groupby = ' ';
651 $groupby = " GROUP BY {$table_name}.postnumber, {$table_name}.blog_id ";
652
653 $orderby = ' visits DESC ';
654 $orderby = " ORDER BY {$orderby} ";
655
656 $limits = $wpdb->prepare( ' LIMIT %d, %d ', $args['offset'], $args['numberposts'] );
657
658 $sql = "SELECT $fields FROM {$table_name} WHERE $where $groupby $orderby $limits";
659 } else {
660 // Single site: existing behaviour filtered by current blog.
661 $fields[] = ( $args['daily'] ) ? "SUM({$table_name}.cntaccess) as visits" : "{$table_name}.cntaccess as visits";
662 $fields[] = "{$wpdb->posts}.ID";
663
664 $fields = implode( ', ', $fields );
665
666 // Create the JOIN clause.
667 $join = " INNER JOIN {$wpdb->posts} ON {$table_name}.postnumber={$wpdb->posts}.ID ";
668
669 // Create the base WHERE clause.
670 $where = $wpdb->prepare( " AND {$table_name}.blog_id = %d ", $args['blog_id'] ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
671 $where .= " AND ($wpdb->posts.post_status = 'publish' OR $wpdb->posts.post_status = 'inherit') "; // Show published posts and attachments.
672 $where .= " AND ($wpdb->posts.post_type <> 'revision' ) "; // No revisions.
673
674 if ( isset( $args['from_date'] ) && ! empty( $args['from_date'] ) ) {
675 $from_date = gmdate( 'Y-m-d', strtotime( $args['from_date'] ) );
676 $where .= $wpdb->prepare( " AND DATE({$table_name}.dp_date) >= DATE(%s) ", $from_date ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
677 }
678
679 if ( isset( $args['to_date'] ) && ! empty( $args['to_date'] ) ) {
680 $to_date = gmdate( 'Y-m-d', strtotime( $args['to_date'] ) );
681 $where .= $wpdb->prepare( " AND DATE({$table_name}.dp_date) <= DATE(%s) ", $to_date ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
682 }
683
684 // Create the base GROUP BY clause.
685 if ( $args['daily'] ) {
686 $groupby = " {$wpdb->posts}.ID";
687 }
688
689 // Create the base ORDER BY clause.
690 $orderby = ' visits DESC ';
691 $orderby = " ORDER BY {$orderby} ";
692
693 // Create the base LIMITS clause.
694 $limits = $wpdb->prepare( ' LIMIT %d, %d ', $args['offset'], $args['numberposts'] );
695
696 if ( ! empty( $groupby ) ) {
697 $groupby = " GROUP BY {$groupby} ";
698 }
699
700 $sql = "SELECT DISTINCT $fields FROM {$table_name} $join WHERE 1=1 $where $groupby $orderby $limits";
701 }
702
703 $result = $wpdb->get_results( $sql, ARRAY_A ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
704
705 return $result;
706 }
707
708 /**
709 * Generates the help tabs.
710 *
711 * @since 3.0.0
712 */
713 public function help_tabs() {
714
715 $screen = get_current_screen();
716
717 $screen->set_help_sidebar(
718 /* translators: 1: Support link. */
719 '<p>' . sprintf( __( 'For more information or how to get support visit the <a href="%1$s">WebberZone support site</a>.', 'top-10' ), esc_url( 'https://webberzone.com/support/' ) ) . '</p>' .
720 /* translators: 1: Forum link. */
721 '<p>' . sprintf( __( 'Support queries should be posted in the <a href="%1$s">WordPress.org support forums</a>.', 'top-10' ), esc_url( 'https://wordpress.org/support/plugin/top-10' ) ) . '</p>' .
722 '<p>' . sprintf(
723 /* translators: 1: Github Issues link, 2: Github page. */
724 __( '<a href="%1$s">Post an issue</a> on <a href="%2$s">GitHub</a> (bug reports only).', 'top-10' ),
725 esc_url( 'https://github.com/WebberZone/top-10/issues' ),
726 esc_url( 'https://github.com/WebberZone/top-10' )
727 ) . '</p>'
728 );
729
730 $screen->add_help_tab(
731 array(
732 'id' => 'tptn-dashboard-general',
733 'title' => __( 'General', 'top-10' ),
734 'content' =>
735 '<p>' . __( 'This screen displays the historical traffic on your site.', 'top-10' ) . '</p>' .
736 /* translators: 1: Constant holding number of days data is stored. */
737 '<p>' . sprintf( __( 'The data is pulled from the daily tables in the database. If you have enabled maintenance then the amount of historical data that is available will be limited to %d days.', 'top-10' ), TOP_TEN_STORE_DATA ) . '</p>' .
738 '<p>' . __( 'You can change this by setting the constant TOP_TEN_STORE_DATA to the number of days of your choice in your wp-config.php.', 'top-10' ) . '</p>',
739 )
740 );
741 }
742 }
743