diff -r be944660c56a -r 3d72ae0968f4 wp/wp-includes/blocks/calendar.php --- a/wp/wp-includes/blocks/calendar.php Wed Sep 21 18:19:35 2022 +0200 +++ b/wp/wp-includes/blocks/calendar.php Tue Sep 27 16:37:53 2022 +0200 @@ -15,6 +15,15 @@ function render_block_core_calendar( $attributes ) { global $monthnum, $year; + // Calendar shouldn't be rendered + // when there are no published posts on the site. + if ( ! block_core_calendar_has_published_posts() ) { + if ( is_user_logged_in() ) { + return '
' . __( 'The calendar block is hidden because there are no published posts.' ) . '
'; + } + return ''; + } + $previous_monthnum = $monthnum; $previous_year = $year; @@ -59,3 +68,86 @@ } add_action( 'init', 'register_block_core_calendar' ); + +/** + * Returns whether or not there are any published posts. + * + * Used to hide the calendar block when there are no published posts. + * This compensates for a known Core bug: https://core.trac.wordpress.org/ticket/12016 + * + * @return bool Has any published posts or not. + */ +function block_core_calendar_has_published_posts() { + // Multisite already has an option that stores the count of the published posts. + // Let's use that for multisites. + if ( is_multisite() ) { + return 0 < (int) get_option( 'post_count' ); + } + + // On single sites we try our own cached option first. + $has_published_posts = get_option( 'wp_calendar_block_has_published_posts', null ); + if ( null !== $has_published_posts ) { + return (bool) $has_published_posts; + } + + // No cache hit, let's update the cache and return the cached value. + return block_core_calendar_update_has_published_posts(); +} + +/** + * Queries the database for any published post and saves + * a flag whether any published post exists or not. + * + * @return bool Has any published posts or not. + */ +function block_core_calendar_update_has_published_posts() { + global $wpdb; + $has_published_posts = (bool) $wpdb->get_var( "SELECT 1 as test FROM {$wpdb->posts} WHERE post_type = 'post' AND post_status = 'publish' LIMIT 1" ); + update_option( 'wp_calendar_block_has_published_posts', $has_published_posts ); + return $has_published_posts; +} + +// We only want to register these functions and actions when +// we are on single sites. On multi sites we use `post_count` option. +if ( ! is_multisite() ) { + /** + * Handler for updating the has published posts flag when a post is deleted. + * + * @param int $post_id Deleted post ID. + */ + function block_core_calendar_update_has_published_post_on_delete( $post_id ) { + $post = get_post( $post_id ); + + if ( ! $post || 'publish' !== $post->post_status || 'post' !== $post->post_type ) { + return; + } + + block_core_calendar_update_has_published_posts(); + } + + /** + * Handler for updating the has published posts flag when a post status changes. + * + * @param string $new_status The status the post is changing to. + * @param string $old_status The status the post is changing from. + * @param WP_Post $post Post object. + */ + function block_core_calendar_update_has_published_post_on_transition_post_status( $new_status, $old_status, $post ) { + if ( $new_status === $old_status ) { + return; + } + + if ( 'post' !== get_post_type( $post ) ) { + return; + } + + if ( 'publish' !== $new_status && 'publish' !== $old_status ) { + return; + } + + block_core_calendar_update_has_published_posts(); + } + + add_action( 'delete_post', 'block_core_calendar_update_has_published_post_on_delete' ); + add_action( 'transition_post_status', 'block_core_calendar_update_has_published_post_on_transition_post_status', 10, 3 ); +}