| @@ -13,9 +13,9 @@ | ||
| 13 | 13 | die; |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | 16 | /** |
| 17 | - * Admin Columns Class. | |
| 17 | + * Registers the Top 10 dashboard widgets and At a Glance items. | |
| 18 | 18 | * |
| 19 | 19 | * @since 3.3.0 |
| 20 | 20 | */ |
| 21 | 21 | class Dashboard_Widgets { |
| @@ -32,8 +32,18 @@ | ||
| 32 | 32 | add_action( 'admin_head-index.php', array( $this, 'dashboard_glance_styles' ) ); |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | 35 | /** |
| 36 | + * Clear cached network dashboard widget output. | |
| 37 | + * | |
| 38 | + * @since 4.5.0 | |
| 39 | + */ | |
| 40 | + public static function clear_network_dashboard_cache() { | |
| 41 | + update_site_option( 'tptn_network_dashboard_cache_version', wp_generate_uuid4() ); | |
| 42 | + delete_site_transient( 'tptn_network_popular_posts_count' ); | |
| 43 | + } | |
| 44 | + | |
| 45 | + /** | |
| 36 | 46 | * Add Top 10 views from the current hour to the At a Glance widget. |
| 37 | 47 | * |
| 38 | 48 | * @since 4.3.0 |
| 39 | 49 | * |
| @@ -178,9 +188,9 @@ | ||
| 178 | 188 | // Add the daily popular posts widget. |
| 179 | 189 | wp_add_dashboard_widget( |
| 180 | 190 | 'tptn_daily_dashboard', |
| 181 | 191 | /* translators: %s: Custom period label (e.g. Daily, Custom (7 days)). */ |
| 182 | - sprintf( __( 'Top 10 - %s Popular Posts', 'top-10' ), Helpers::get_daily_range_label() ), | |
| 192 | + sprintf( __( 'Top 10 - %s Popular Posts', 'top-10' ), Helpers::get_daily_range_label( 1 ) ), | |
| 183 | 193 | array( __CLASS__, 'popular_posts_widget_daily' ), |
| 184 | 194 | array( __CLASS__, 'pop_display' ) |
| 185 | 195 | ); |
| 186 | 196 | |
| @@ -222,9 +232,9 @@ | ||
| 222 | 232 | // Add the daily popular posts widget. |
| 223 | 233 | wp_add_dashboard_widget( |
| 224 | 234 | 'tptn_network_daily_dashboard', |
| 225 | 235 | /* translators: %s: Custom period label (e.g. Daily, Custom (7 days)). */ |
| 226 | - sprintf( __( 'Top 10 - Network %s Popular Posts', 'top-10' ), Helpers::get_daily_range_label() ), | |
| 236 | + sprintf( __( 'Top 10 - Network %s Popular Posts', 'top-10' ), Helpers::get_daily_range_label( 1 ) ), | |
| 227 | 237 | array( __CLASS__, 'network_popular_posts_widget_daily' ), |
| 228 | 238 | array( __CLASS__, 'pop_display' ) |
| 229 | 239 | ); |
| 230 | 240 | |
| @@ -254,8 +264,42 @@ | ||
| 254 | 264 | if ( ! $limit ) { |
| 255 | 265 | $limit = \tptn_get_option( 'limit' ); |
| 256 | 266 | } |
| 257 | 267 | |
| 268 | + $cache_key = ''; | |
| 269 | + $cache_ttl = 0; | |
| 270 | + if ( $network && $widget ) { | |
| 271 | + /** | |
| 272 | + * Filters how long the network dashboard widget output is cached. | |
| 273 | + * | |
| 274 | + * @since 4.5.0 | |
| 275 | + * | |
| 276 | + * @param int $cache_ttl Cache lifetime in seconds. Default 15 minutes. | |
| 277 | + */ | |
| 278 | + $cache_ttl = max( 0, (int) apply_filters( 'tptn_network_dashboard_cache_ttl', 15 * MINUTE_IN_SECONDS ) ); | |
| 279 | + $cache_key = 'tptn_network_dashboard_' . md5( | |
| 280 | + (string) wp_json_encode( | |
| 281 | + array( | |
| 282 | + 'version' => get_site_option( 'tptn_network_dashboard_cache_version', '1' ), | |
| 283 | + 'daily' => (bool) $daily, | |
| 284 | + 'orderby' => $daily ? 'daily_count' : 'total_count', | |
| 285 | + 'order' => 'DESC', | |
| 286 | + 'from_date' => current_time( 'Y-m-d' ), | |
| 287 | + 'to_date' => current_time( 'Y-m-d' ), | |
| 288 | + 'page' => (int) $page, | |
| 289 | + 'limit' => (int) $limit, | |
| 290 | + ) | |
| 291 | + ) | |
| 292 | + ); | |
| 293 | + | |
| 294 | + if ( $cache_ttl > 0 ) { | |
| 295 | + $cached = get_site_transient( $cache_key ); | |
| 296 | + if ( false !== $cached ) { | |
| 297 | + return $cached; | |
| 298 | + } | |
| 299 | + } | |
| 300 | + } | |
| 301 | + | |
| 258 | 302 | $args = array(); |
| 259 | 303 | $visits = 'total_count'; |
| 260 | 304 | if ( $daily ) { |
| 261 | 305 | $args['orderby'] = 'daily_count'; |
| @@ -272,8 +316,12 @@ | ||
| 272 | 316 | if ( ! absint( $result[ $visits ] ) ) { |
| 273 | 317 | continue; |
| 274 | 318 | } |
| 275 | 319 | |
| 320 | + $context_key = class_exists( 'WebberZone\\Top_Ten\\Pro\\Sitewide_Database' ) && \WebberZone\Top_Ten\Pro\Sitewide_Database::is_available() | |
| 321 | + ? \WebberZone\Top_Ten\Pro\Sitewide_Database::get_context_key( $result['ID'], $result['blog_id'] ?? null ) | |
| 322 | + : ''; | |
| 323 | + | |
| 276 | 324 | // Handle network context differently. |
| 277 | 325 | if ( $network ) { |
| 278 | 326 | // Check if blog exists. |
| 279 | 327 | $blog_details = get_blog_details( $result['blog_id'] ); |
| @@ -280,24 +328,34 @@ | ||
| 280 | 328 | if ( ! $blog_details ) { |
| 281 | 329 | continue; // Skip if blog doesn't exist. |
| 282 | 330 | } |
| 283 | 331 | |
| 284 | - // Get post from specific blog. | |
| 285 | - $post = get_blog_post( $result['blog_id'], $result['ID'] ); | |
| 286 | - if ( ! $post || 'publish' !== $post->post_status ) { | |
| 287 | - continue; // Skip if post doesn't exist or isn't published. | |
| 332 | + if ( '' !== $context_key ) { | |
| 333 | + $label = \WebberZone\Top_Ten\Pro\Sitewide_Database::get_context_label( $context_key ); | |
| 334 | + $output .= '<li>' . esc_html( $label ) . ' <span class="tptn-sitewide-label">(' . esc_html__( 'site-wide', 'top-10' ) . ')</span>'; | |
| 335 | + } else { | |
| 336 | + // Get post from specific blog. | |
| 337 | + $post = get_blog_post( $result['blog_id'], $result['ID'] ); | |
| 338 | + if ( ! $post || 'publish' !== $post->post_status ) { | |
| 339 | + continue; // Skip if post doesn't exist or isn't published. | |
| 340 | + } | |
| 341 | + | |
| 342 | + $output .= '<li><a href="' . get_blog_permalink( $result['blog_id'], $result['ID'] ) . '">' . esc_html( $post->post_title ) . '</a>'; | |
| 288 | 343 | } |
| 289 | - | |
| 290 | - $output .= '<li><a href="' . get_blog_permalink( $result['blog_id'], $result['ID'] ) . '">' . esc_html( $post->post_title ) . '</a>'; | |
| 291 | 344 | $output .= ' (' . Helpers::number_format_i18n( $result[ $visits ] ) . ')'; |
| 292 | 345 | $output .= ' <span class="tptn-blog-name">- ' . esc_html( $blog_details->blogname ) . '</span>'; |
| 293 | 346 | $output .= '</li>'; |
| 294 | 347 | } else { |
| 295 | 348 | // Single site context. |
| 296 | - if ( ! get_post_status( $result['ID'] ) ) { | |
| 297 | - continue; | |
| 349 | + if ( '' !== $context_key ) { | |
| 350 | + $label = \WebberZone\Top_Ten\Pro\Sitewide_Database::get_context_label( $context_key ); | |
| 351 | + $output .= '<li>' . esc_html( $label ) . ' <span class="tptn-sitewide-label">(' . esc_html__( 'site-wide', 'top-10' ) . ')</span>'; | |
| 352 | + } else { | |
| 353 | + if ( ! get_post_status( $result['ID'] ) ) { | |
| 354 | + continue; | |
| 355 | + } | |
| 356 | + $output .= '<li><a href="' . get_permalink( $result['ID'] ) . '">' . get_the_title( $result['ID'] ) . '</a>'; | |
| 298 | 357 | } |
| 299 | - $output .= '<li><a href="' . get_permalink( $result['ID'] ) . '">' . get_the_title( $result['ID'] ) . '</a>'; | |
| 300 | 358 | $output .= ' (' . Helpers::number_format_i18n( $result[ $visits ] ) . ')'; |
| 301 | 359 | $output .= '</li>'; |
| 302 | 360 | } |
| 303 | 361 | } |
| @@ -349,9 +407,15 @@ | ||
| 349 | 407 | * @param int $limit Limit of posts |
| 350 | 408 | * @param bool $widget Is this a widget |
| 351 | 409 | * @param bool $network Is this network-wide |
| 352 | 410 | */ |
| 353 | - return apply_filters( 'tptn_popular_posts_widget_output', $output, $daily, $page, $limit, $widget, $network ); | |
| 411 | + $output = apply_filters( 'tptn_popular_posts_widget_output', $output, $daily, $page, $limit, $widget, $network ); | |
| 412 | + | |
| 413 | + if ( $network && $widget && $cache_ttl > 0 ) { | |
| 414 | + set_site_transient( $cache_key, $output, $cache_ttl ); | |
| 415 | + } | |
| 416 | + | |
| 417 | + return $output; | |
| 354 | 418 | } |
| 355 | 419 | |
| 356 | 420 | |
| 357 | 421 | /** |