| @@ -23,8 +23,15 @@ | ||
| 23 | 23 | */ |
| 24 | 24 | class Blocks { |
| 25 | 25 | |
| 26 | 26 | /** |
| 27 | + * Request-local cache for post counts rendered by the Post Count block. | |
| 28 | + * | |
| 29 | + * @var array<string, int|string> | |
| 30 | + */ | |
| 31 | + private static $post_count_cache = array(); | |
| 32 | + | |
| 33 | + /** | |
| 27 | 34 | * Register blocks with WordPress. |
| 28 | 35 | */ |
| 29 | 36 | public function __construct() { |
| 30 | 37 | Hook_Registry::add_action( 'init', array( $this, 'register_blocks' ) ); |
| @@ -32,8 +39,22 @@ | ||
| 32 | 39 | Hook_Registry::add_filter( 'block_editor_rest_api_preload_paths', array( $this, 'add_custom_preload_paths' ) ); |
| 33 | 40 | } |
| 34 | 41 | |
| 35 | 42 | /** |
| 43 | + * Add custom preload paths for the REST API. | |
| 44 | + * | |
| 45 | + * @since 4.5.0 | |
| 46 | + * | |
| 47 | + * @param array $preload_paths Existing preload paths. | |
| 48 | + * @return array Modified preload paths. | |
| 49 | + */ | |
| 50 | + public static function add_custom_preload_paths( $preload_paths ) { | |
| 51 | + $preload_paths[] = '/wp/v2/top-10/v1/counter'; | |
| 52 | + | |
| 53 | + return $preload_paths; | |
| 54 | + } | |
| 55 | + | |
| 56 | + /** | |
| 36 | 57 | * Registers the block using the metadata loaded from the `block.json` file. |
| 37 | 58 | * Behind the scenes, it registers also all assets so they can be enqueued |
| 38 | 59 | * through the block editor in the corresponding context. |
| 39 | 60 | * |
| @@ -40,9 +61,9 @@ | ||
| 40 | 61 | * @since 3.1.0 |
| 41 | 62 | */ |
| 42 | 63 | public function register_blocks() { |
| 43 | 64 | // Define an array of blocks with their paths and optional render callbacks. |
| 44 | - $blocks = array( | |
| 65 | + $blocks = array( | |
| 45 | 66 | 'popular-posts' => array( |
| 46 | 67 | 'path' => __DIR__ . '/build/popular-posts/', |
| 47 | 68 | 'render_callback' => array( $this, 'render_block_popular_posts' ), |
| 48 | 69 | ), |
| @@ -50,8 +71,9 @@ | ||
| 50 | 71 | 'path' => __DIR__ . '/build/post-count/', |
| 51 | 72 | 'render_callback' => array( $this, 'render_block_post_count' ), |
| 52 | 73 | ), |
| 53 | 74 | ); |
| 75 | + $default_blocks = $blocks; | |
| 54 | 76 | |
| 55 | 77 | /** |
| 56 | 78 | * Filters the blocks registered by the plugin. |
| 57 | 79 | * |
| @@ -58,10 +80,31 @@ | ||
| 58 | 80 | * @since 4.0.0 |
| 59 | 81 | * |
| 60 | 82 | * @param array $blocks Array of blocks registered by the plugin. |
| 61 | 83 | */ |
| 62 | - $blocks = apply_filters( 'tptn_register_blocks', $blocks ); | |
| 84 | + $blocks = apply_filters( 'tptn_register_blocks', $blocks ); | |
| 85 | + $manifest = __DIR__ . '/build/blocks-manifest.php'; | |
| 63 | 86 | |
| 87 | + if ( function_exists( 'wp_register_block_types_from_metadata_collection' ) && file_exists( $manifest ) ) { | |
| 88 | + wp_register_block_types_from_metadata_collection( __DIR__ . '/build', $manifest ); | |
| 89 | + | |
| 90 | + // Register any blocks added or changed by the filter that fall outside the manifest. | |
| 91 | + foreach ( $blocks as $block_name => $block_data ) { | |
| 92 | + if ( isset( $default_blocks[ $block_name ] ) && $default_blocks[ $block_name ] === $block_data ) { | |
| 93 | + continue; | |
| 94 | + } | |
| 95 | + | |
| 96 | + $args = array(); | |
| 97 | + if ( isset( $block_data['render_callback'] ) ) { | |
| 98 | + $args['render_callback'] = $block_data['render_callback']; | |
| 99 | + } | |
| 100 | + | |
| 101 | + register_block_type( $block_data['path'], $args ); | |
| 102 | + } | |
| 103 | + | |
| 104 | + return; | |
| 105 | + } | |
| 106 | + | |
| 64 | 107 | // Loop through each block and register it. |
| 65 | 108 | foreach ( $blocks as $block_name => $block_data ) { |
| 66 | 109 | $args = array(); |
| 67 | 110 | |
| @@ -86,10 +129,9 @@ | ||
| 86 | 129 | |
| 87 | 130 | $attributes['extra_class'] = isset( $attributes['className'] ) ? esc_attr( $attributes['className'] ) : ''; |
| 88 | 131 | |
| 89 | 132 | $defaults = array_merge( |
| 90 | - \tptn_settings_defaults(), | |
| 91 | - \tptn_get_settings(), | |
| 133 | + \tptn_get_settings_with_defaults(), | |
| 92 | 134 | array( |
| 93 | 135 | 'is_block' => 1, |
| 94 | 136 | ) |
| 95 | 137 | ); |
| @@ -155,10 +197,10 @@ | ||
| 155 | 197 | $output = ''; |
| 156 | 198 | $args = array(); |
| 157 | 199 | |
| 158 | 200 | $post_id = absint( $block->context['postId'] ); |
| 159 | - $counter = isset( $attributes['counter'] ) ? $attributes['counter'] : 'total'; | |
| 160 | - $blog_id = isset( $attributes['blogId'] ) ? $attributes['blogId'] : get_current_blog_id(); | |
| 201 | + $counter_type = isset( $attributes['counter'] ) ? $attributes['counter'] : 'total'; | |
| 202 | + $blog_id = isset( $attributes['blogId'] ) ? absint( $attributes['blogId'] ) : get_current_blog_id(); | |
| 161 | 203 | $from_date = isset( $attributes['fromDate'] ) ? $attributes['fromDate'] : ''; |
| 162 | 204 | $to_date = isset( $attributes['toDate'] ) ? $attributes['toDate'] : ''; |
| 163 | 205 | $text_before = isset( $attributes['textBefore'] ) ? $attributes['textBefore'] : ''; |
| 164 | 206 | $text_after = isset( $attributes['textAfter'] ) ? $attributes['textAfter'] : ''; |
| @@ -179,10 +221,8 @@ | ||
| 179 | 221 | if ( ! empty( $to_date ) ) { |
| 180 | 222 | $args['to_date'] = $to_date; |
| 181 | 223 | } |
| 182 | 224 | |
| 183 | - $counter = Counter::get_post_count_only( $post_id, $counter, $blog_id, $args ); | |
| 184 | - | |
| 185 | 225 | $classes = array(); |
| 186 | 226 | $classes[] = 'wp-block-tptn-post-count'; |
| 187 | 227 | $classes[] = 'tptn-post-count'; |
| 188 | 228 | |
| @@ -192,22 +232,24 @@ | ||
| 192 | 232 | if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) { |
| 193 | 233 | $classes[] = 'has-link-color'; |
| 194 | 234 | } |
| 195 | 235 | |
| 196 | - if ( ! $advanced_mode ) { | |
| 197 | - $output = sprintf( | |
| 236 | + $counter = null; | |
| 237 | + if ( ! $advanced_mode || empty( $text_advanced ) ) { | |
| 238 | + $counter = self::get_cached_post_count( $post_id, $counter_type, $blog_id, $args ); | |
| 239 | + $output = sprintf( | |
| 198 | 240 | '%1$s%2$s%3$s', |
| 199 | 241 | wp_kses_post( (string) $text_before ), |
| 200 | 242 | esc_html( (string) $counter ), |
| 201 | 243 | wp_kses_post( (string) $text_after ) |
| 202 | 244 | ); |
| 203 | - } elseif ( ! empty( $text_advanced ) ) { | |
| 245 | + } else { | |
| 204 | 246 | $classes[] = 'tptn-advanced-mode'; |
| 205 | 247 | $output = $text_advanced; |
| 206 | 248 | |
| 207 | 249 | foreach ( array( 'total', 'daily', 'overall' ) as $type ) { |
| 208 | 250 | if ( false !== strpos( $text_advanced, "%{$type}count%" ) ) { |
| 209 | - $count = Counter::get_post_count_only( $post_id, $type, $blog_id, $args ); | |
| 251 | + $count = self::get_cached_post_count( $post_id, $type, $blog_id, $args ); | |
| 210 | 252 | |
| 211 | 253 | $output = str_replace( |
| 212 | 254 | "%{$type}count%", |
| 213 | 255 | (string) $count, |
| @@ -258,9 +300,8 @@ | ||
| 258 | 300 | $icon = sprintf( |
| 259 | 301 | '<span class="tptn-post-count-icon">%1$s</span>', |
| 260 | 302 | wp_kses( $svg_code_with_style, self::get_allowed_svg_tags() ) |
| 261 | 303 | ); |
| 262 | - $icon = '<span class="tptn-post-count-icon">' . $svg_code_with_style . '</span>'; | |
| 263 | 304 | } |
| 264 | 305 | if ( ! empty( $icon ) ) { |
| 265 | 306 | if ( 'before' === $svg_icon_location ) { |
| 266 | 307 | $output = $icon . $output; |
| @@ -278,8 +319,27 @@ | ||
| 278 | 319 | ); |
| 279 | 320 | } |
| 280 | 321 | |
| 281 | 322 | /** |
| 323 | + * Get a request-cached post count. | |
| 324 | + * | |
| 325 | + * @param int $post_id Post ID. | |
| 326 | + * @param string $counter Counter type. | |
| 327 | + * @param int $blog_id Blog ID. | |
| 328 | + * @param array $args Additional counter arguments. | |
| 329 | + * @return int|string Post count. | |
| 330 | + */ | |
| 331 | + private static function get_cached_post_count( $post_id, $counter, $blog_id, $args ) { | |
| 332 | + $cache_key = md5( (string) wp_json_encode( array( $post_id, $counter, $blog_id, $args ) ) ); | |
| 333 | + | |
| 334 | + if ( ! array_key_exists( $cache_key, self::$post_count_cache ) ) { | |
| 335 | + self::$post_count_cache[ $cache_key ] = Counter::get_post_count_only( $post_id, $counter, $blog_id, $args ); | |
| 336 | + } | |
| 337 | + | |
| 338 | + return self::$post_count_cache[ $cache_key ]; | |
| 339 | + } | |
| 340 | + | |
| 341 | + /** | |
| 282 | 342 | * Get allowed SVG tags for wp_kses. |
| 283 | 343 | * |
| 284 | 344 | * @since 4.0.0 |
| 285 | 345 | * |
| @@ -465,20 +525,6 @@ | ||
| 465 | 525 | ); |
| 466 | 526 | wp_add_inline_style( "popular-posts-block-editor-{$style}", $extra_css ); |
| 467 | 527 | } |
| 468 | 528 | } |
| 469 | - } | |
| 470 | - | |
| 471 | - /** | |
| 472 | - * Add custom preload paths for the REST API. | |
| 473 | - * | |
| 474 | - * @since 4.0.0 | |
| 475 | - * | |
| 476 | - * @param array $preload_paths Existing preload paths. | |
| 477 | - * @return array Modified preload paths. | |
| 478 | - */ | |
| 479 | - public static function add_custom_preload_paths( $preload_paths ) { | |
| 480 | - $preload_paths[] = '/wp/v2/top-10/v1/counter'; | |
| 481 | - | |
| 482 | - return $preload_paths; | |
| 483 | 529 | } |
| 484 | 530 | } |