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-widgets.php

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

428 lines 12.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Dashboard Widgets class.
4 *
5 * @package WebberZone\Top_Ten\Admin
6 */
7
8 namespace WebberZone\Top_Ten\Admin;
9
10 use WebberZone\Top_Ten\Util\Helpers;
11
12 if ( ! defined( 'WPINC' ) ) {
13 die;
14 }
15
16 /**
17 * Admin Columns Class.
18 *
19 * @since 3.3.0
20 */
21 class Dashboard_Widgets {
22
23 /**
24 * Constructor class.
25 *
26 * @since 3.3.0
27 */
28 public function __construct() {
29 add_filter( 'wp_dashboard_setup', array( $this, 'wp_dashboard_setup' ) );
30 add_filter( 'wp_network_dashboard_setup', array( $this, 'wp_network_dashboard_setup' ) );
31 add_filter( 'dashboard_glance_items', array( $this, 'dashboard_glance_items' ) );
32 add_action( 'admin_head-index.php', array( $this, 'dashboard_glance_styles' ) );
33 }
34
35 /**
36 * Add Top 10 views from the current hour to the At a Glance widget.
37 *
38 * @since 4.3.0
39 *
40 * @param string[] $items Array of extra At a Glance items.
41 * @return string[] Modified array of extra At a Glance items.
42 */
43 public function dashboard_glance_items( $items ) {
44 if ( ! current_user_can( 'manage_options' ) && ! \tptn_get_option( 'show_count_non_admins' ) ) {
45 return $items;
46 }
47
48 $current_hour = current_time( 'Y-m-d H' );
49 $hour_views = self::get_current_hour_views();
50 $day_views = self::get_views_for_period( current_time( 'Y-m-d 00' ), $current_hour );
51
52 $items[] = self::get_glance_item(
53 $hour_views,
54 /* translators: %s: Number of views in the last hour. */
55 _n( '%s view in the last hour', '%s views in the last hour', $hour_views, 'top-10' ),
56 admin_url( 'admin.php?page=tptn_dashboard' )
57 );
58
59 $items[] = self::get_glance_item(
60 $day_views,
61 /* translators: %s: Number of views in the past day. */
62 _n( '%s view in the past day', '%s views in the past day', $day_views, 'top-10' ),
63 wp_nonce_url(
64 add_query_arg(
65 array(
66 'page' => 'tptn_dashboard',
67 'post-date-filter-from' => current_time( 'd M Y' ),
68 'post-date-filter-to' => current_time( 'd M Y' ),
69 ),
70 admin_url( 'admin.php' )
71 ),
72 'tptn-dashboard'
73 )
74 );
75
76 return $items;
77 }
78
79 /**
80 * Add a better icon for Top 10 At a Glance items.
81 *
82 * @since 4.3.0
83 */
84 public function dashboard_glance_styles() {
85 ?>
86 <style>
87 #dashboard_right_now li a.tptn-glance-views:before {
88 content: "\f239";
89 content: "\f239" / "";
90 }
91 </style>
92 <?php
93 }
94
95 /**
96 * Get the number of views recorded in the current hour.
97 *
98 * Top 10 stores daily counts in hourly buckets, so this returns the current
99 * hour bucket rather than a rolling 60-minute window.
100 *
101 * @since 4.3.0
102 *
103 * @return int Number of views in the current hour.
104 */
105 public static function get_current_hour_views() {
106 return self::get_views_for_period( current_time( 'Y-m-d H' ), current_time( 'Y-m-d H' ) );
107 }
108
109 /**
110 * Get the number of views recorded in a period.
111 *
112 * @since 4.3.0
113 *
114 * @param string $from_hour Start hour in Y-m-d H format.
115 * @param string $to_hour End hour in Y-m-d H format.
116 * @return int Number of views in the period.
117 */
118 public static function get_views_for_period( $from_hour, $to_hour ) {
119 global $wpdb;
120
121 $table = $wpdb->base_prefix . 'top_ten_daily';
122 $sql = $wpdb->prepare(
123 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
124 "SELECT SUM(cntaccess) FROM {$table} WHERE dp_date >= %s AND dp_date <= %s AND blog_id = %d",
125 $from_hour,
126 $to_hour,
127 get_current_blog_id()
128 );
129 $views = $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
130
131 return (int) $views;
132 }
133
134 /**
135 * Build a Top 10 At a Glance item.
136 *
137 * @since 4.3.0
138 *
139 * @param int $views Views.
140 * @param string $label Label with a %s placeholder for the formatted count.
141 * @param string $url Link URL.
142 * @return string At a Glance item markup.
143 */
144 public static function get_glance_item( $views, $label, $url ) {
145 return sprintf(
146 '<a class="tptn-glance-views" href="%1$s">%2$s</a>',
147 esc_url( $url ),
148 esc_html( sprintf( $label, Helpers::number_format_i18n( $views ) ) )
149 );
150 }
151
152 /**
153 * Function to add the widgets to the Dashboard.
154 *
155 * @since 3.3.0
156 */
157 public static function wp_dashboard_setup() {
158
159 /**
160 * Filter whether to register the dashboard widgets.
161 *
162 * @since 3.3.0
163 *
164 * @param bool $dashboard_setup Whether to register the dashboard widgets.
165 */
166 $dashboard_setup = apply_filters( 'tptn_dashboard_setup', true );
167
168 if ( $dashboard_setup && ( current_user_can( 'manage_options' ) || \tptn_get_option( 'show_count_non_admins' ) ) ) {
169
170 // Add the overall popular posts widget.
171 wp_add_dashboard_widget(
172 'tptn_overall_dashboard',
173 __( 'Top 10 - Overall Popular Posts', 'top-10' ),
174 array( __CLASS__, 'popular_posts_widget' ),
175 array( __CLASS__, 'pop_display' )
176 );
177
178 // Add the daily popular posts widget.
179 wp_add_dashboard_widget(
180 'tptn_daily_dashboard',
181 __( 'Top 10 - Daily Popular Posts', 'top-10' ),
182 array( __CLASS__, 'popular_posts_widget_daily' ),
183 array( __CLASS__, 'pop_display' )
184 );
185
186 // Add the mini views overview widget.
187 wp_add_dashboard_widget(
188 'tptn_views_over_time_dashboard',
189 __( 'Top 10 Views Overview', 'top-10' ),
190 array( __CLASS__, 'views_over_time_widget' ),
191 );
192 }
193 }
194
195 /**
196 * Function to add the widgets to the Network Dashboard.
197 *
198 * @since 4.2.0
199 */
200 public static function wp_network_dashboard_setup() {
201
202 /**
203 * Filter whether to register the network dashboard widgets.
204 *
205 * @since 4.2.0
206 *
207 * @param bool $dashboard_setup Whether to register the network dashboard widgets.
208 */
209 $dashboard_setup = apply_filters( 'tptn_network_dashboard_setup', true );
210
211 if ( $dashboard_setup && current_user_can( 'manage_network' ) ) {
212
213 // Add the overall popular posts widget.
214 wp_add_dashboard_widget(
215 'tptn_network_overall_dashboard',
216 __( 'Top 10 - Network Popular Posts', 'top-10' ),
217 array( __CLASS__, 'network_popular_posts_widget' ),
218 array( __CLASS__, 'pop_display' )
219 );
220
221 // Add the daily popular posts widget.
222 wp_add_dashboard_widget(
223 'tptn_network_daily_dashboard',
224 __( 'Top 10 - Network Daily Popular Posts', 'top-10' ),
225 array( __CLASS__, 'network_popular_posts_widget_daily' ),
226 array( __CLASS__, 'pop_display' )
227 );
228
229 // Add the mini views overview widget to network dashboard.
230 wp_add_dashboard_widget(
231 'tptn_network_views_over_time_dashboard',
232 __( 'Top 10 Network Views Overview', 'top-10' ),
233 array( __CLASS__, 'views_over_time_widget' ),
234 );
235 }
236 }
237
238 /**
239 * Create the Dashboard Widget and content of the Popular pages
240 *
241 * @since 3.3.0
242 *
243 * @param bool $daily Switch for Daily or Overall popular posts.
244 * @param int $page Which page of the lists are on.
245 * @param int $limit Maximum number of posts per page.
246 * @param bool $widget Is this a WordPress widget.
247 * @param bool $network Whether to show network-wide posts.
248 * @return string Formatted list of popular posts
249 */
250 public static function pop_display( $daily = false, $page = 0, $limit = 0, $widget = true, $network = false ) {
251
252 if ( ! $limit ) {
253 $limit = \tptn_get_option( 'limit' );
254 }
255
256 $args = array();
257 $visits = 'total_count';
258 if ( $daily ) {
259 $args['orderby'] = 'daily_count';
260 $visits = 'daily_count';
261 }
262 $statistics_table = new Statistics_Table( $network );
263 $results = $statistics_table->get_popular_posts( $limit, $page + 1, $args );
264
265 $output = '<div id="tptn_popular_posts' . ( $daily ? '_daily' : '' ) . '">';
266
267 if ( $results ) {
268 $output .= '<ul>';
269 foreach ( $results as $result ) {
270 if ( ! absint( $result[ $visits ] ) ) {
271 continue;
272 }
273
274 // Handle network context differently.
275 if ( $network ) {
276 // Check if blog exists.
277 $blog_details = get_blog_details( $result['blog_id'] );
278 if ( ! $blog_details ) {
279 continue; // Skip if blog doesn't exist.
280 }
281
282 // Get post from specific blog.
283 $post = get_blog_post( $result['blog_id'], $result['ID'] );
284 if ( ! $post || 'publish' !== $post->post_status ) {
285 continue; // Skip if post doesn't exist or isn't published.
286 }
287
288 $output .= '<li><a href="' . get_blog_permalink( $result['blog_id'], $result['ID'] ) . '">' . esc_html( $post->post_title ) . '</a>';
289 $output .= ' (' . Helpers::number_format_i18n( $result[ $visits ] ) . ')';
290 $output .= ' <span class="tptn-blog-name">- ' . esc_html( $blog_details->blogname ) . '</span>';
291 $output .= '</li>';
292 } else {
293 // Single site context.
294 if ( ! get_post_status( $result['ID'] ) ) {
295 continue;
296 }
297 $output .= '<li><a href="' . get_permalink( $result['ID'] ) . '">' . get_the_title( $result['ID'] ) . '</a>';
298 $output .= ' (' . Helpers::number_format_i18n( $result[ $visits ] ) . ')';
299 $output .= '</li>';
300 }
301 }
302 $output .= '</ul>';
303 }
304
305 $output .= '<p style="text-align:center">';
306
307 if ( $daily ) {
308 if ( $network ) {
309 $output .= '<a href="' . network_admin_url( 'admin.php?page=tptn_network_pop_posts_page&orderby=daily_count&order=desc' ) . '">' . __( 'View all network daily popular posts', 'top-10' ) . '</a>';
310 } else {
311 $output .= '<a href="' . esc_url(
312 add_query_arg(
313 array(
314 'page' => 'tptn_popular_posts',
315 'orderby' => 'daily_count',
316 'order' => 'desc',
317 'post-date-filter-from' => current_time( 'd M Y' ),
318 'post-date-filter-to' => current_time( 'd M Y' ),
319 ),
320 admin_url( 'admin.php' )
321 )
322 ) . '">' . __( 'View all daily popular posts', 'top-10' ) . '</a>';
323 }
324 } elseif ( $network ) {
325 $output .= '<a href="' . network_admin_url( 'admin.php?page=tptn_network_pop_posts_page&orderby=total_count&order=desc' ) . '">' . __( 'View all network popular posts', 'top-10' ) . '</a>';
326 } else {
327 $output .= '<a href="' . admin_url( 'admin.php?page=tptn_popular_posts&orderby=total_count&order=desc' ) . '">' . __( 'View all popular posts', 'top-10' ) . '</a>';
328 }
329
330 $output .= '</p>';
331
332 $output .= '<p style="text-align:center;border-top: #000 1px solid">';
333
334 /* translators: 1: Top 10 page link. */
335 $output .= sprintf( __( 'Popular posts by <a href="%s" target="_blank">Top 10 plugin</a>', 'top-10' ), esc_url( 'https://webberzone.com/plugins/top-10/' ) );
336 $output .= '</p>';
337 $output .= '</div>';
338
339 /**
340 * Filters the dashboard widget output
341 *
342 * @since 3.3.0
343 *
344 * @param string $output Widget output
345 * @param bool $daily Is this a daily widget
346 * @param int $page Page number
347 * @param int $limit Limit of posts
348 * @param bool $widget Is this a widget
349 * @param bool $network Is this network-wide
350 */
351 return apply_filters( 'tptn_popular_posts_widget_output', $output, $daily, $page, $limit, $widget, $network );
352 }
353
354
355 /**
356 * Widget for Popular Posts.
357 *
358 * @since 3.3.0
359 */
360 public static function popular_posts_widget() {
361 echo self::pop_display( false ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
362 }
363
364
365 /**
366 * Widget for Daily Popular Posts.
367 *
368 * @since 3.3.0
369 */
370 public static function popular_posts_widget_daily() {
371 echo self::pop_display( true ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
372 }
373
374 /**
375 * Widget for Network Popular Posts.
376 *
377 * @since 4.2.0
378 */
379 public static function network_popular_posts_widget() {
380 echo self::pop_display( false, 0, 0, true, true ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
381 }
382
383 /**
384 * Widget for Network Daily Popular Posts.
385 *
386 * @since 4.2.0
387 */
388 public static function network_popular_posts_widget_daily() {
389 echo self::pop_display( true, 0, 0, true, true ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
390 }
391
392 /**
393 * Widget for Views Overview (mini chart).
394 *
395 * @since 4.2.0
396 */
397 public static function views_over_time_widget() {
398 global $tptn_freemius;
399
400 $output = '<div class="tptn-views-over-time-widget">';
401
402 if ( ! $tptn_freemius->is_paying() ) {
403 $output .= sprintf(
404 '<div class="tptn-views-over-time-chart-placeholder" style="height:150px;margin-bottom:15px;border:1px dashed #ccd0d4;background:#f8f9fa;display:flex;align-items:center;justify-content:center;color:#6c757d;font-style:italic;">%s</div>',
405 esc_html__( 'Upgrade to Top 10 Pro to see your views over time chart here.', 'top-10' )
406 );
407 $output .= sprintf(
408 '<p style="text-align:center;"><a class="button button-primary" href="%s">%s</a></p>',
409 esc_url( $tptn_freemius->get_upgrade_url() ),
410 esc_html__( 'Upgrade to Pro', 'top-10' )
411 );
412 }
413
414 $output .= '</div>';
415
416 /**
417 * Filters the views over time widget content.
418 *
419 * @since 4.2.0
420 *
421 * @param string $output The widget content.
422 */
423 $output = apply_filters( 'tptn_views_over_time_widget_content', $output );
424
425 echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
426 }
427 }
428