PluginProbe
Gutenberg / 24.0.0
Gutenberg v24.0.0
24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 All 403 releases
← All changes | build/scripts/block-library/latest-posts.php +63 -21 23.2.2 → 24.0.0 View file →
@@ -43,8 +43,9 @@
43 43 * @return string Returns the post content with latest posts added.
44 44 */
45 45 function gutenberg_render_block_core_latest_posts( $attributes ) {
46 46 global $post, $block_core_latest_posts_excerpt_length;
47 + static $rendering_stack = array();
47 48
48 49 $args = array(
49 50 'posts_per_page' => $attributes['postsToShow'],
50 51 'post_status' => 'publish',
@@ -56,17 +57,17 @@
56 57
57 58 $block_core_latest_posts_excerpt_length = $attributes['excerptLength'];
58 59 add_filter( 'excerpt_length', 'gutenberg_block_core_latest_posts_get_excerpt_length', 20 );
59 60
60 - if ( ! empty( $attributes['categories'] ) ) {
61 - $args['category__in'] = array_column( $attributes['categories'], 'id' );
61 + $categories = $attributes['categories'] ?? null;
62 + if ( ! empty( $categories ) && is_array( $categories ) ) {
63 + $args['category__in'] = array_column( $categories, 'id' );
62 64 }
63 65 if ( isset( $attributes['selectedAuthor'] ) ) {
64 66 $args['author'] = $attributes['selectedAuthor'];
65 67 }
66 68
67 - $query = new WP_Query();
68 - $recent_posts = $query->query( $args );
69 + $query = new WP_Query( $args );
69 70
70 71 if ( isset( $attributes['displayFeaturedImage'] ) && $attributes['displayFeaturedImage'] ) {
71 72 update_post_thumbnail_cache( $query );
72 73 }
@@ -71,12 +72,18 @@
71 72 update_post_thumbnail_cache( $query );
72 73 }
73 74
74 75 $list_items_markup = '';
76 + // Snapshot the current global post so it can be restored after the loop.
77 + // We use have_posts()/the_post() rather than foreach so that setup_postdata()
78 + // is called for each post, establishing the correct global context for
79 + // do_blocks() and other filters that run during full-content rendering.
80 + $previous_post = $post ?? null;
75 81
76 - foreach ( $recent_posts as $post ) {
77 - $post_link = esc_url( get_permalink( $post ) );
78 - $title = get_the_title( $post );
82 + while ( $query->have_posts() ) {
83 + $query->the_post();
84 + $post_link = esc_url( get_permalink() );
85 + $title = get_the_title();
79 86
80 87 if ( ! $title ) {
81 88 $title = __( '(no title)' );
82 89 }
@@ -82,9 +89,9 @@
82 89 }
83 90
84 91 $list_items_markup .= '<li>';
85 92
86 - if ( $attributes['displayFeaturedImage'] && has_post_thumbnail( $post ) ) {
93 + if ( $attributes['displayFeaturedImage'] && has_post_thumbnail() ) {
87 94 $image_style = '';
88 95 if ( isset( $attributes['featuredImageSizeWidth'] ) ) {
89 96 $image_style .= sprintf( 'max-width:%spx;', $attributes['featuredImageSizeWidth'] );
90 97 }
@@ -97,9 +104,9 @@
97 104 $image_classes .= ' align' . $attributes['featuredImageAlign'];
98 105 }
99 106
100 107 $featured_image = get_the_post_thumbnail(
101 - $post,
108 + null,
102 109 $attributes['featuredImageSizeSlug'],
103 110 array(
104 111 'style' => esc_attr( $image_style ),
105 112 )
@@ -125,9 +132,9 @@
125 132 $title
126 133 );
127 134
128 135 if ( isset( $attributes['displayAuthor'] ) && $attributes['displayAuthor'] ) {
129 - $author_display_name = get_the_author_meta( 'display_name', $post->post_author );
136 + $author_display_name = get_the_author_meta( 'display_name' );
130 137
131 138 /* translators: byline. %s: author. */
132 139 $byline = sprintf( __( 'by %s' ), $author_display_name );
133 140
@@ -141,10 +148,10 @@
141 148
142 149 if ( isset( $attributes['displayPostDate'] ) && $attributes['displayPostDate'] ) {
143 150 $list_items_markup .= sprintf(
144 151 '<time datetime="%1$s" class="wp-block-latest-posts__post-date">%2$s</time>',
145 - esc_attr( get_the_date( 'c', $post ) ),
146 - get_the_date( '', $post )
152 + esc_attr( get_the_date( 'c' ) ),
153 + get_the_date( '' )
147 154 );
148 155 }
149 156
150 157 if ( isset( $attributes['displayPostContent'] ) && $attributes['displayPostContent']
@@ -149,9 +156,9 @@
149 156
150 157 if ( isset( $attributes['displayPostContent'] ) && $attributes['displayPostContent']
151 158 && isset( $attributes['displayPostContentRadio'] ) && 'excerpt' === $attributes['displayPostContentRadio'] ) {
152 159
153 - $trimmed_excerpt = get_the_excerpt( $post );
160 + $trimmed_excerpt = get_the_excerpt();
154 161
155 162 /*
156 163 * Adds a "Read more" link with screen reader text.
157 164 * [&hellip;] is the default excerpt ending from wp_trim_excerpt() in Core.
@@ -169,9 +176,9 @@
169 176 );
170 177 }
171 178 }
172 179
173 - if ( post_password_required( $post ) ) {
180 + if ( post_password_required() ) {
174 181 $trimmed_excerpt = __( 'This content is password protected.' );
175 182 }
176 183
177 184 $list_items_markup .= sprintf(
@@ -182,17 +189,32 @@
182 189
183 190 if ( isset( $attributes['displayPostContent'] ) && $attributes['displayPostContent']
184 191 && isset( $attributes['displayPostContentRadio'] ) && 'full_post' === $attributes['displayPostContentRadio'] ) {
185 192
186 - $post_content = html_entity_decode( $post->post_content, ENT_QUOTES, get_option( 'blog_charset' ) );
193 + if ( post_password_required() ) {
194 + $post_content = __( 'This content is password protected.' );
195 + } else {
196 + $post_id = get_the_ID();
197 + $post_content = get_post_field( 'post_content', $post_id, 'raw' );
198 + // Check if we're already rendering this post to prevent infinite recursion.
199 + if ( in_array( $post_id, $rendering_stack, true ) ) {
200 + $post_content = '';
201 + } else {
202 + $rendering_stack[] = $post_id;
187 203
188 - if ( post_password_required( $post ) ) {
189 - $post_content = __( 'This content is password protected.' );
204 + try {
205 + // Run through the actions that are typically taken on the_content.
206 + $post_content = _wp_apply_block_content_filters( $post_content, 'latest-posts' );
207 + } finally {
208 + array_pop( $rendering_stack );
209 + }
210 + }
190 211 }
191 212
213 + $post_content = str_replace( ']]>', ']]&gt;', $post_content );
192 214 $list_items_markup .= sprintf(
193 215 '<div class="wp-block-latest-posts__post-full-content">%1$s</div>',
194 - wp_kses_post( $post_content )
216 + $post_content
195 217 );
196 218 }
197 219
198 220 $list_items_markup .= "</li>\n";
@@ -197,16 +219,36 @@
197 219
198 220 $list_items_markup .= "</li>\n";
199 221 }
200 222
223 + // Restore the post context that was active before this secondary query.
224 + // wp_reset_postdata() is intentionally not used here: when this block is
225 + // rendered inside another post's content (e.g. via do_blocks()), it would
226 + // restore to the main query post rather than the outer rendering post.
227 + $post = $previous_post;
228 + if ( $previous_post instanceof WP_Post ) {
229 + setup_postdata( $previous_post );
230 + }
231 +
201 232 remove_filter( 'excerpt_length', 'gutenberg_block_core_latest_posts_get_excerpt_length', 20 );
202 233
234 + $layout = $attributes['layout'] ?? array();
235 + $legacy_layout_type = (
236 + isset( $attributes['postLayout'] ) &&
237 + 'grid' === $attributes['postLayout']
238 + ) ? 'grid' : 'default';
239 + $layout_type = $layout['type'] ?? $legacy_layout_type;
240 + $column_count = $layout['columnCount'] ?? ( $attributes['columns'] ?? null );
241 +
203 242 $classes = array( 'wp-block-latest-posts__list' );
204 - if ( isset( $attributes['postLayout'] ) && 'grid' === $attributes['postLayout'] ) {
243 + if ( 'grid' === $layout_type ) {
205 244 $classes[] = 'is-grid';
206 245 }
207 - if ( isset( $attributes['columns'] ) && 'grid' === $attributes['postLayout'] ) {
208 - $classes[] = 'columns-' . $attributes['columns'];
246 + if ( 'grid' === $layout_type && ! empty( $column_count ) ) {
247 + $classes[] = sanitize_title( 'columns-' . $column_count );
248 + }
249 + if ( 'grid' === $layout_type && ! empty( $column_count ) && ! empty( $layout['minimumColumnWidth'] ) ) {
250 + $classes[] = 'has-native-responsive-grid';
209 251 }
210 252 if ( isset( $attributes['displayPostDate'] ) && $attributes['displayPostDate'] ) {
211 253 $classes[] = 'has-dates';
212 254 }