PluginProbe
Gutenberg / 22.3.0
Gutenberg v22.3.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 7.4.0 All 402 releases
gutenberg / build / scripts / block-library / latest-posts.php

latest-posts.php in Gutenberg 22.3.0, at build/scripts/block-library/latest-posts.php

274 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Server-side rendering of the `core/latest-posts` block.
4 *
5 * @package WordPress
6 */
7
8 /**
9 * The excerpt length set by the Latest Posts core block
10 * set at render time and used by the block itself.
11 *
12 * @var int
13 */
14 global $block_core_latest_posts_excerpt_length;
15 $block_core_latest_posts_excerpt_length = 0;
16
17 /**
18 * Callback for the excerpt_length filter used by
19 * the Latest Posts block at render time.
20 *
21 * @since 5.4.0
22 *
23 * @return int Returns the global $block_core_latest_posts_excerpt_length variable
24 * to allow the excerpt_length filter respect the Latest Block setting.
25 */
26 function gutenberg_block_core_latest_posts_get_excerpt_length() {
27 global $block_core_latest_posts_excerpt_length;
28 return $block_core_latest_posts_excerpt_length;
29 }
30
31 /**
32 * Renders the `core/latest-posts` block on server.
33 *
34 * @since 5.0.0
35 *
36 * @global WP_Post $post Global post object.
37 * @global int $block_core_latest_posts_excerpt_length Excerpt length set by the Latest Posts core block.
38 *
39 * @param array $attributes The block attributes.
40 *
41 * @return string Returns the post content with latest posts added.
42 */
43 function gutenberg_render_block_core_latest_posts( $attributes ) {
44 global $post, $block_core_latest_posts_excerpt_length;
45
46 $args = array(
47 'posts_per_page' => $attributes['postsToShow'],
48 'post_status' => 'publish',
49 'order' => $attributes['order'],
50 'orderby' => $attributes['orderBy'],
51 'ignore_sticky_posts' => true,
52 'no_found_rows' => true,
53 );
54
55 $block_core_latest_posts_excerpt_length = $attributes['excerptLength'];
56 add_filter( 'excerpt_length', 'gutenberg_block_core_latest_posts_get_excerpt_length', 20 );
57
58 if ( ! empty( $attributes['categories'] ) ) {
59 $args['category__in'] = array_column( $attributes['categories'], 'id' );
60 }
61 if ( isset( $attributes['selectedAuthor'] ) ) {
62 $args['author'] = $attributes['selectedAuthor'];
63 }
64
65 $query = new WP_Query();
66 $recent_posts = $query->query( $args );
67
68 if ( isset( $attributes['displayFeaturedImage'] ) && $attributes['displayFeaturedImage'] ) {
69 update_post_thumbnail_cache( $query );
70 }
71
72 $list_items_markup = '';
73
74 foreach ( $recent_posts as $post ) {
75 $post_link = esc_url( get_permalink( $post ) );
76 $title = get_the_title( $post );
77
78 if ( ! $title ) {
79 $title = __( '(no title)' );
80 }
81
82 $list_items_markup .= '<li>';
83
84 if ( $attributes['displayFeaturedImage'] && has_post_thumbnail( $post ) ) {
85 $image_style = '';
86 if ( isset( $attributes['featuredImageSizeWidth'] ) ) {
87 $image_style .= sprintf( 'max-width:%spx;', $attributes['featuredImageSizeWidth'] );
88 }
89 if ( isset( $attributes['featuredImageSizeHeight'] ) ) {
90 $image_style .= sprintf( 'max-height:%spx;', $attributes['featuredImageSizeHeight'] );
91 }
92
93 $image_classes = 'wp-block-latest-posts__featured-image';
94 if ( isset( $attributes['featuredImageAlign'] ) ) {
95 $image_classes .= ' align' . $attributes['featuredImageAlign'];
96 }
97
98 $featured_image = get_the_post_thumbnail(
99 $post,
100 $attributes['featuredImageSizeSlug'],
101 array(
102 'style' => esc_attr( $image_style ),
103 )
104 );
105 if ( $attributes['addLinkToFeaturedImage'] ) {
106 $featured_image = sprintf(
107 '<a href="%1$s" aria-label="%2$s">%3$s</a>',
108 esc_url( $post_link ),
109 esc_attr( $title ),
110 $featured_image
111 );
112 }
113 $list_items_markup .= sprintf(
114 '<div class="%1$s">%2$s</div>',
115 esc_attr( $image_classes ),
116 $featured_image
117 );
118 }
119
120 $list_items_markup .= sprintf(
121 '<a class="wp-block-latest-posts__post-title" href="%1$s">%2$s</a>',
122 esc_url( $post_link ),
123 $title
124 );
125
126 if ( isset( $attributes['displayAuthor'] ) && $attributes['displayAuthor'] ) {
127 $author_display_name = get_the_author_meta( 'display_name', $post->post_author );
128
129 /* translators: byline. %s: author. */
130 $byline = sprintf( __( 'by %s' ), $author_display_name );
131
132 if ( ! empty( $author_display_name ) ) {
133 $list_items_markup .= sprintf(
134 '<div class="wp-block-latest-posts__post-author">%1$s</div>',
135 $byline
136 );
137 }
138 }
139
140 if ( isset( $attributes['displayPostDate'] ) && $attributes['displayPostDate'] ) {
141 $list_items_markup .= sprintf(
142 '<time datetime="%1$s" class="wp-block-latest-posts__post-date">%2$s</time>',
143 esc_attr( get_the_date( 'c', $post ) ),
144 get_the_date( '', $post )
145 );
146 }
147
148 if ( isset( $attributes['displayPostContent'] ) && $attributes['displayPostContent']
149 && isset( $attributes['displayPostContentRadio'] ) && 'excerpt' === $attributes['displayPostContentRadio'] ) {
150
151 $trimmed_excerpt = get_the_excerpt( $post );
152
153 /*
154 * Adds a "Read more" link with screen reader text.
155 * [&hellip;] is the default excerpt ending from wp_trim_excerpt() in Core.
156 */
157 if ( str_ends_with( $trimmed_excerpt, ' [&hellip;]' ) ) {
158 /** This filter is documented in wp-includes/formatting.php */
159 $excerpt_length = (int) apply_filters( 'excerpt_length', $block_core_latest_posts_excerpt_length );
160 if ( $excerpt_length <= $block_core_latest_posts_excerpt_length ) {
161 $trimmed_excerpt = substr( $trimmed_excerpt, 0, -11 );
162 $trimmed_excerpt .= sprintf(
163 /* translators: 1: A URL to a post, 2: Hidden accessibility text: Post title */
164 __( '… <a class="wp-block-latest-posts__read-more" href="%1$s" rel="noopener noreferrer">Read more<span class="screen-reader-text">: %2$s</span></a>' ),
165 esc_url( $post_link ),
166 esc_html( $title )
167 );
168 }
169 }
170
171 if ( post_password_required( $post ) ) {
172 $trimmed_excerpt = __( 'This content is password protected.' );
173 }
174
175 $list_items_markup .= sprintf(
176 '<div class="wp-block-latest-posts__post-excerpt">%1$s</div>',
177 $trimmed_excerpt
178 );
179 }
180
181 if ( isset( $attributes['displayPostContent'] ) && $attributes['displayPostContent']
182 && isset( $attributes['displayPostContentRadio'] ) && 'full_post' === $attributes['displayPostContentRadio'] ) {
183
184 $post_content = html_entity_decode( $post->post_content, ENT_QUOTES, get_option( 'blog_charset' ) );
185
186 if ( post_password_required( $post ) ) {
187 $post_content = __( 'This content is password protected.' );
188 }
189
190 $list_items_markup .= sprintf(
191 '<div class="wp-block-latest-posts__post-full-content">%1$s</div>',
192 wp_kses_post( $post_content )
193 );
194 }
195
196 $list_items_markup .= "</li>\n";
197 }
198
199 remove_filter( 'excerpt_length', 'gutenberg_block_core_latest_posts_get_excerpt_length', 20 );
200
201 $classes = array( 'wp-block-latest-posts__list' );
202 if ( isset( $attributes['postLayout'] ) && 'grid' === $attributes['postLayout'] ) {
203 $classes[] = 'is-grid';
204 }
205 if ( isset( $attributes['columns'] ) && 'grid' === $attributes['postLayout'] ) {
206 $classes[] = 'columns-' . $attributes['columns'];
207 }
208 if ( isset( $attributes['displayPostDate'] ) && $attributes['displayPostDate'] ) {
209 $classes[] = 'has-dates';
210 }
211 if ( isset( $attributes['displayAuthor'] ) && $attributes['displayAuthor'] ) {
212 $classes[] = 'has-author';
213 }
214 if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) {
215 $classes[] = 'has-link-color';
216 }
217
218 $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => implode( ' ', $classes ) ) );
219
220 return sprintf(
221 '<ul %1$s>%2$s</ul>',
222 $wrapper_attributes,
223 $list_items_markup
224 );
225 }
226
227 /**
228 * Registers the `core/latest-posts` block on server.
229 *
230 * @since 5.0.0
231 */
232 function gutenberg_register_block_core_latest_posts() {
233 register_block_type_from_metadata(
234 __DIR__ . '/latest-posts',
235 array(
236 'render_callback' => 'gutenberg_render_block_core_latest_posts',
237 )
238 );
239 }
240 add_action( 'init', 'gutenberg_register_block_core_latest_posts', 20 );
241
242 /**
243 * Handles outdated versions of the `core/latest-posts` block by converting
244 * attribute `categories` from a numeric string to an array with key `id`.
245 *
246 * This is done to accommodate the changes introduced in #20781 that sought to
247 * add support for multiple categories to the block. However, given that this
248 * block is dynamic, the usual provisions for block migration are insufficient,
249 * as they only act when a block is loaded in the editor.
250 *
251 * TODO: Remove when and if the bottom client-side deprecation for this block
252 * is removed.
253 *
254 * @since 5.5.0
255 *
256 * @param array $block A single parsed block object.
257 *
258 * @return array The migrated block object.
259 */
260 function gutenberg_block_core_latest_posts_migrate_categories( $block ) {
261 if (
262 'core/latest-posts' === $block['blockName'] &&
263 ! empty( $block['attrs']['categories'] ) &&
264 is_string( $block['attrs']['categories'] )
265 ) {
266 $block['attrs']['categories'] = array(
267 array( 'id' => absint( $block['attrs']['categories'] ) ),
268 );
269 }
270
271 return $block;
272 }
273 add_filter( 'render_block_data', 'gutenberg_block_core_latest_posts_migrate_categories' );
274