Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 318 |
|
0.00% |
0 / 10 |
CRAP | n/a |
0 / 0 |
|
| newspack_blocks_hpb_maximum_image_width | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
90 | |||
| newspack_blocks_filter_hpb_sizes | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
42 | |||
| newspack_blocks_retrieve_homepage_articles_blocks | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
20 | |||
| newspack_blocks_collect_all_attribute_values | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
30 | |||
| newspack_blocks_get_homepage_articles_css_string | |
0.00% |
0 / 76 |
|
0.00% |
0 / 1 |
110 | |||
| newspack_blocks_render_block_homepage_articles | |
0.00% |
0 / 120 |
|
0.00% |
0 / 1 |
1640 | |||
| newspack_blocks_register_homepage_articles | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
2 | |||
| newspack_blocks_format_avatars | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
2 | |||
| newspack_blocks_format_byline | |
0.00% |
0 / 28 |
|
0.00% |
0 / 1 |
20 | |||
| newspack_blocks_format_categories | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
56 | |||
| 1 | <?php |
| 2 | /** |
| 3 | * Server-side rendering of the `newspack-blocks/homepage-posts` block. |
| 4 | * |
| 5 | * @package WordPress |
| 6 | */ |
| 7 | |
| 8 | /** |
| 9 | * Calculate the maximum width of an image in the Homepage Posts block. |
| 10 | */ |
| 11 | function newspack_blocks_hpb_maximum_image_width() { |
| 12 | $max_width = 0; |
| 13 | |
| 14 | global $newspack_blocks_hpb_rendering_context; |
| 15 | if ( isset( $newspack_blocks_hpb_rendering_context['attrs'] ) ) { |
| 16 | $attributes = $newspack_blocks_hpb_rendering_context['attrs']; |
| 17 | if ( empty( $attributes ) ) { |
| 18 | return $max_width; |
| 19 | } |
| 20 | if ( isset( $attributes['align'] ) && in_array( $attributes['align'], [ 'full', 'wide' ], true ) ) { |
| 21 | // For full and wide alignments, the image width is more than 100% of the content width |
| 22 | // and depends on site width. Can't make assumptions about the site width. |
| 23 | return $max_width; |
| 24 | } |
| 25 | $site_content_width = 1200; |
| 26 | $is_image_half_width = in_array( $attributes['mediaPosition'], [ 'left', 'right' ], true ); |
| 27 | if ( 'grid' === $attributes['postLayout'] ) { |
| 28 | $columns = absint( $attributes['columns'] ); |
| 29 | if ( $is_image_half_width ) { |
| 30 | // If the media position is on left or right, the image is 50% of the column width. |
| 31 | $columns = $columns * 2; |
| 32 | } |
| 33 | return $site_content_width / $columns; |
| 34 | } elseif ( 'list' === $attributes['postLayout'] && $is_image_half_width ) { |
| 35 | return $site_content_width / 2; |
| 36 | } |
| 37 | } |
| 38 | return $max_width; |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | * Set image `sizes` attribute based on the maximum image width. |
| 43 | * |
| 44 | * @param array $sizes Sizes for the sizes attribute. |
| 45 | */ |
| 46 | function newspack_blocks_filter_hpb_sizes( $sizes ) { |
| 47 | if ( defined( 'NEWSPACK_DISABLE_HPB_IMAGE_OPTIMISATION' ) && NEWSPACK_DISABLE_HPB_IMAGE_OPTIMISATION ) { |
| 48 | // Allow disabling the image optimisation per-site. |
| 49 | return $sizes; |
| 50 | } |
| 51 | global $newspack_blocks_hpb_current_theme; |
| 52 | if ( ! $newspack_blocks_hpb_current_theme ) { |
| 53 | $newspack_blocks_hpb_current_theme = wp_get_theme()->template; |
| 54 | } |
| 55 | if ( stripos( $newspack_blocks_hpb_current_theme, 'newspack' ) === false ) { |
| 56 | // Bail if not using a Newspack theme – assumptions about the site content width can't be made then. |
| 57 | return $sizes; |
| 58 | } |
| 59 | $max_width = newspack_blocks_hpb_maximum_image_width(); |
| 60 | if ( 0 !== $max_width ) { |
| 61 | // >=782px is the desktop size – set width as computed. |
| 62 | $sizes = '(min-width: 782px) ' . $max_width . 'px'; |
| 63 | // Between 600-782px is the tablet size – all columns will collapse to two-column layout |
| 64 | // (assuming 5% padding on each side and between columns). |
| 65 | $sizes .= ', (min-width: 600px) 42.5vw'; |
| 66 | // <=600px is the mobile size – columns will stack to full width |
| 67 | // (assumming 5% side padding on each side). |
| 68 | $sizes .= ', 90vw'; |
| 69 | } |
| 70 | return $sizes; |
| 71 | } |
| 72 | |
| 73 | /** |
| 74 | * Retrieve Homepage Articles blocks from blocks, recursively. |
| 75 | * |
| 76 | * @param array $blocks The blocks to search. |
| 77 | * @param string $block_name The block name to search for. |
| 78 | */ |
| 79 | function newspack_blocks_retrieve_homepage_articles_blocks( $blocks, $block_name ) { |
| 80 | $ha_blocks = []; |
| 81 | foreach ( $blocks as $block ) { |
| 82 | if ( $block_name === $block['blockName'] ) { |
| 83 | $ha_blocks = array_merge( $ha_blocks, [ $block ] ); |
| 84 | } |
| 85 | if ( is_array( $block['innerBlocks'] ) ) { |
| 86 | $ha_blocks = array_merge( $ha_blocks, newspack_blocks_retrieve_homepage_articles_blocks( $block['innerBlocks'], $block_name ) ); |
| 87 | } |
| 88 | } |
| 89 | return $ha_blocks; |
| 90 | } |
| 91 | |
| 92 | /** |
| 93 | * Collect all attributes' values used in a set of blocks. |
| 94 | * |
| 95 | * @param array $blocks The blocks to search. |
| 96 | */ |
| 97 | function newspack_blocks_collect_all_attribute_values( $blocks ) { |
| 98 | $result = []; |
| 99 | |
| 100 | foreach ( $blocks as $block ) { |
| 101 | foreach ( $block as $key => $value ) { |
| 102 | if ( ! isset( $result[ $key ] ) ) { |
| 103 | $result[ $key ] = []; |
| 104 | } |
| 105 | if ( ! in_array( $value, $result[ $key ], true ) ) { |
| 106 | $result[ $key ][] = $value; |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | return $result; |
| 112 | } |
| 113 | |
| 114 | /** |
| 115 | * Output a CSS string based on attributes used in a set of blocks. |
| 116 | * This is to mitigate CLS. Any CSS that might cause CLS should be output here, |
| 117 | * inline and before the blocks are printed. |
| 118 | * |
| 119 | * @param array $attrs The attributes used in the blocks. |
| 120 | */ |
| 121 | function newspack_blocks_get_homepage_articles_css_string( $attrs ) { |
| 122 | $entry_title_type_scale = [ |
| 123 | '0.7em', |
| 124 | '0.9em', |
| 125 | '1em', |
| 126 | '1.2em', |
| 127 | '1.4em', |
| 128 | '1.7em', |
| 129 | '2em', |
| 130 | '2.2em', |
| 131 | '2.4em', |
| 132 | '2.6em', |
| 133 | ]; |
| 134 | |
| 135 | ob_start(); |
| 136 | ?> |
| 137 | .wp-block-newspack-blocks-homepage-articles article .entry-title { |
| 138 | font-size: 1.2em; |
| 139 | } |
| 140 | .wp-block-newspack-blocks-homepage-articles .entry-meta { |
| 141 | display: flex; |
| 142 | flex-wrap: wrap; |
| 143 | align-items: center; |
| 144 | margin-top: 0.5em; |
| 145 | } |
| 146 | .wp-block-newspack-blocks-homepage-articles article .entry-meta { |
| 147 | font-size: 0.8em; |
| 148 | } |
| 149 | .wp-block-newspack-blocks-homepage-articles article .avatar { |
| 150 | height: 25px; |
| 151 | width: 25px; |
| 152 | } |
| 153 | .wp-block-newspack-blocks-homepage-articles .post-thumbnail{ |
| 154 | margin: 0; |
| 155 | margin-bottom: 0.25em; |
| 156 | } |
| 157 | .wp-block-newspack-blocks-homepage-articles .post-thumbnail img { |
| 158 | height: auto; |
| 159 | width: 100%; |
| 160 | } |
| 161 | .wp-block-newspack-blocks-homepage-articles .post-thumbnail figcaption { |
| 162 | margin-bottom: 0.5em; |
| 163 | } |
| 164 | .wp-block-newspack-blocks-homepage-articles p { |
| 165 | margin: 0.5em 0; |
| 166 | } |
| 167 | |
| 168 | <?php |
| 169 | if ( isset( $attrs['typeScale'] ) ) { |
| 170 | foreach ( $attrs['typeScale'] as $scale ) { |
| 171 | echo esc_html( |
| 172 | ".wpnbha.ts-$scale .entry-title{font-size: {$entry_title_type_scale[$scale - 1]}}" |
| 173 | ); |
| 174 | if ( in_array( $scale, [ 8, 9, 10 ], true ) ) { |
| 175 | echo esc_html( |
| 176 | ".wpnbha.ts-$scale .entry-title {line-height: 1.1;}" |
| 177 | ); |
| 178 | } |
| 179 | if ( in_array( $scale, [ 7, 8, 9, 10 ], true ) ) { |
| 180 | echo esc_html( |
| 181 | ".wpnbha.ts-$scale .newspack-post-subtitle {font-size: 1.4em;}" |
| 182 | ); |
| 183 | } |
| 184 | if ( in_array( $scale, [ 6 ], true ) ) { |
| 185 | echo esc_html( |
| 186 | ".wpnbha.ts-$scale article .newspack-post-subtitle {font-size: 1.4em;}" |
| 187 | ); |
| 188 | } |
| 189 | if ( in_array( $scale, [ 5 ], true ) ) { |
| 190 | echo esc_html( |
| 191 | ".wpnbha.ts-$scale article .newspack-post-subtitle {font-size: 1.2em;}" |
| 192 | ); |
| 193 | } |
| 194 | if ( in_array( $scale, [ 1, 2, 3 ], true ) ) { |
| 195 | echo esc_html( |
| 196 | ".wpnbha.ts-$scale article .newspack-post-subtitle, .wpnbha.ts-$scale article .entry-wrapper p, .wpnbha.ts-$scale article .entry-wrapper .more-link, .wpnbha.ts-$scale article .entry-meta {font-size: 0.8em;}" |
| 197 | ); |
| 198 | } |
| 199 | } |
| 200 | } |
| 201 | if ( isset( $attrs['showSubtitle'] ) && in_array( 1, $attrs['showSubtitle'], false ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.FoundNonStrictFalse |
| 202 | echo esc_html( |
| 203 | '.newspack-post-subtitle--in-homepage-block { |
| 204 | margin-top: 0.3em; |
| 205 | margin-bottom: 0; |
| 206 | line-height: 1.4; |
| 207 | font-style: italic; |
| 208 | }' |
| 209 | ); |
| 210 | } |
| 211 | ?> |
| 212 | <?php |
| 213 | return ob_get_clean(); |
| 214 | } |
| 215 | |
| 216 | /** |
| 217 | * Renders the `newspack-blocks/homepage-posts` block on server. |
| 218 | * |
| 219 | * @param array $attributes The block attributes. |
| 220 | * |
| 221 | * @return string Returns the post content with latest posts added. |
| 222 | */ |
| 223 | function newspack_blocks_render_block_homepage_articles( $attributes ) { |
| 224 | // Don't output the block inside RSS feeds. |
| 225 | if ( is_feed() ) { |
| 226 | return; |
| 227 | } |
| 228 | |
| 229 | $block_name = apply_filters( 'newspack_blocks_block_name', 'newspack-blocks/homepage-articles' ); |
| 230 | $article_query = new WP_Query( Newspack_Blocks::build_articles_query( $attributes, $block_name ) ); |
| 231 | if ( ! $article_query->have_posts() ) { |
| 232 | return; |
| 233 | } |
| 234 | |
| 235 | // Gather all Homepage Articles blocks on the page and output only the needed CSS. |
| 236 | // This CSS will be printed along with the first found block markup. |
| 237 | global $newspack_blocks_hpb_all_blocks; |
| 238 | $inline_style_html = ''; |
| 239 | if ( ! is_array( $newspack_blocks_hpb_all_blocks ) ) { |
| 240 | $newspack_blocks_hpb_all_blocks = newspack_blocks_retrieve_homepage_articles_blocks( |
| 241 | parse_blocks( get_the_content() ), |
| 242 | $block_name |
| 243 | ); |
| 244 | $all_used_attrs = newspack_blocks_collect_all_attribute_values( array_column( $newspack_blocks_hpb_all_blocks, 'attrs' ) ); |
| 245 | $css_string = newspack_blocks_get_homepage_articles_css_string( $all_used_attrs ); |
| 246 | ob_start(); |
| 247 | ?> |
| 248 | <style id="newspack-blocks-inline-css" type="text/css"><?php echo esc_html( $css_string ); ?></style> |
| 249 | <?php |
| 250 | $inline_style_html = ob_get_clean(); |
| 251 | } |
| 252 | |
| 253 | // This will let the FSE plugin know we need CSS/JS now. |
| 254 | do_action( 'newspack_blocks_render_homepage_articles' ); |
| 255 | |
| 256 | $classes = Newspack_Blocks::block_classes( 'homepage-articles', $attributes, [ 'wpnbha' ] ); |
| 257 | |
| 258 | if ( isset( $attributes['postLayout'] ) && 'grid' === $attributes['postLayout'] ) { |
| 259 | $classes .= ' is-grid'; |
| 260 | } |
| 261 | if ( isset( $attributes['columns'] ) && 'grid' === $attributes['postLayout'] ) { |
| 262 | $classes .= ' columns-' . $attributes['columns'] . ' colgap-' . $attributes['colGap']; |
| 263 | } |
| 264 | if ( $attributes['showImage'] ) { |
| 265 | $classes .= ' show-image'; |
| 266 | } |
| 267 | if ( $attributes['showImage'] && isset( $attributes['mediaPosition'] ) ) { |
| 268 | $classes .= ' image-align' . $attributes['mediaPosition']; |
| 269 | } |
| 270 | if ( isset( $attributes['typeScale'] ) ) { |
| 271 | $classes .= ' ts-' . $attributes['typeScale']; |
| 272 | } |
| 273 | if ( $attributes['showImage'] && isset( $attributes['imageScale'] ) ) { |
| 274 | $classes .= ' is-' . $attributes['imageScale']; |
| 275 | } |
| 276 | if ( $attributes['showImage'] ) { |
| 277 | $classes .= ' is-' . $attributes['imageShape']; |
| 278 | } |
| 279 | if ( $attributes['showImage'] && $attributes['mobileStack'] ) { |
| 280 | $classes .= ' mobile-stack'; |
| 281 | } |
| 282 | if ( $attributes['showCaption'] ) { |
| 283 | $classes .= ' show-caption'; |
| 284 | } |
| 285 | if ( $attributes['showCredit'] ) { |
| 286 | $classes .= ' show-credit'; |
| 287 | } |
| 288 | if ( $attributes['showCategory'] ) { |
| 289 | $classes .= ' show-category'; |
| 290 | } |
| 291 | if ( isset( $attributes['className'] ) ) { |
| 292 | $classes .= ' ' . $attributes['className']; |
| 293 | } |
| 294 | if ( $attributes['textAlign'] ) { |
| 295 | $classes .= ' has-text-align-' . $attributes['textAlign']; |
| 296 | } |
| 297 | |
| 298 | if ( '' !== $attributes['textColor'] || '' !== $attributes['customTextColor'] ) { |
| 299 | $classes .= ' has-text-color'; |
| 300 | } |
| 301 | if ( '' !== $attributes['textColor'] ) { |
| 302 | $classes .= ' has-' . $attributes['textColor'] . '-color'; |
| 303 | } |
| 304 | |
| 305 | $styles = ''; |
| 306 | |
| 307 | if ( '' !== $attributes['customTextColor'] ) { |
| 308 | $styles = 'color: ' . $attributes['customTextColor'] . ';'; |
| 309 | } |
| 310 | |
| 311 | // Handle custom taxonomies. |
| 312 | if ( isset( $attributes['customTaxonomies'] ) ) { |
| 313 | $custom_taxes = $attributes['customTaxonomies']; |
| 314 | unset( $attributes['customTaxonomies'] ); |
| 315 | if ( is_array( $custom_taxes ) && ! empty( $custom_taxes ) ) { |
| 316 | foreach ( $custom_taxes as $tax ) { |
| 317 | if ( ! empty( $tax['slug'] ) && ! empty( $tax['terms'] ) ) { |
| 318 | $attributes[ $tax['slug'] ] = $tax['terms']; |
| 319 | } |
| 320 | } |
| 321 | } |
| 322 | } |
| 323 | |
| 324 | $articles_rest_url = add_query_arg( |
| 325 | array_merge( |
| 326 | map_deep( |
| 327 | $attributes, |
| 328 | function( $attribute ) { |
| 329 | return false === $attribute ? '0' : rawurlencode( $attribute ); |
| 330 | } |
| 331 | ), |
| 332 | [ |
| 333 | 'page' => 2, |
| 334 | ] |
| 335 | ), |
| 336 | rest_url( '/newspack-blocks/v1/articles' ) |
| 337 | ); |
| 338 | |
| 339 | $page = $article_query->paged ?? 1; |
| 340 | |
| 341 | $has_more_pages = ( ++$page ) <= $article_query->max_num_pages; |
| 342 | |
| 343 | /** |
| 344 | * Hide the "More" button on private sites. |
| 345 | * |
| 346 | * Client-side fetching from a private WP.com blog requires authentication, |
| 347 | * which is not provided in the current implementation. |
| 348 | * See https://github.com/Automattic/newspack-blocks/issues/306. |
| 349 | */ |
| 350 | $is_blog_private = (int) get_option( 'blog_public' ) === -1; |
| 351 | |
| 352 | $has_more_button = ! $is_blog_private && $has_more_pages && (bool) $attributes['moreButton']; |
| 353 | |
| 354 | if ( $has_more_button ) { |
| 355 | $classes .= ' has-more-button'; |
| 356 | } |
| 357 | |
| 358 | ob_start(); |
| 359 | |
| 360 | ?> |
| 361 | <div |
| 362 | class="<?php echo esc_attr( $classes ); ?>" |
| 363 | style="<?php echo esc_attr( $styles ); ?>" |
| 364 | > |
| 365 | <?php echo $inline_style_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> |
| 366 | <div data-posts data-current-post-id="<?php the_ID(); ?>"> |
| 367 | <?php if ( '' !== $attributes['sectionHeader'] ) : ?> |
| 368 | <h2 class="article-section-title"> |
| 369 | <span><?php echo wp_kses_post( $attributes['sectionHeader'] ); ?></span> |
| 370 | </h2> |
| 371 | <?php endif; ?> |
| 372 | <?php |
| 373 | echo Newspack_Blocks::template_inc( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 374 | __DIR__ . '/templates/articles-list.php', |
| 375 | [ |
| 376 | 'articles_rest_url' => $articles_rest_url, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 377 | 'article_query' => $article_query, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 378 | 'attributes' => $attributes, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 379 | ] |
| 380 | ); |
| 381 | ?> |
| 382 | </div> |
| 383 | <?php |
| 384 | |
| 385 | if ( $has_more_button ) : |
| 386 | $load_more = ''; |
| 387 | if ( (bool) $attributes['infiniteScroll'] ) { |
| 388 | $load_more = 'data-infinite-scroll="true"'; |
| 389 | } |
| 390 | ?> |
| 391 | <button type="button" class="wp-block-button__link" <?php echo esc_attr( $load_more ); ?> data-next="<?php echo esc_url( $articles_rest_url ); ?>"> |
| 392 | <span class="label"> |
| 393 | <?php |
| 394 | if ( ! empty( $attributes['moreButtonText'] ) ) { |
| 395 | echo esc_html( $attributes['moreButtonText'] ); |
| 396 | } else { |
| 397 | esc_html_e( 'Load more posts', 'jetpack-mu-wpcom' ); |
| 398 | } |
| 399 | ?> |
| 400 | </span> |
| 401 | <span class="loading"></span> |
| 402 | </button> |
| 403 | <p class="error"> |
| 404 | <?php esc_html_e( 'Something went wrong. Please refresh the page and/or try again.', 'jetpack-mu-wpcom' ); ?> |
| 405 | </p> |
| 406 | |
| 407 | <?php endif; ?> |
| 408 | |
| 409 | </div> |
| 410 | <?php |
| 411 | |
| 412 | $content = ob_get_clean(); |
| 413 | Newspack_Blocks::enqueue_view_assets( 'homepage-articles' ); |
| 414 | |
| 415 | return $content; |
| 416 | } |
| 417 | |
| 418 | /** |
| 419 | * Registers the `newspack-blocks/homepage-articles` block on server. |
| 420 | */ |
| 421 | function newspack_blocks_register_homepage_articles() { |
| 422 | $block = json_decode( |
| 423 | file_get_contents( __DIR__ . '/block.json' ), // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents |
| 424 | true |
| 425 | ); |
| 426 | register_block_type( |
| 427 | apply_filters( 'newspack_blocks_block_name', 'newspack-blocks/' . $block['name'] ), |
| 428 | apply_filters( |
| 429 | 'newspack_blocks_block_args', |
| 430 | array( |
| 431 | 'attributes' => $block['attributes'], |
| 432 | 'render_callback' => 'newspack_blocks_render_block_homepage_articles', |
| 433 | 'supports' => [], |
| 434 | ), |
| 435 | $block['name'] |
| 436 | ) |
| 437 | ); |
| 438 | } |
| 439 | add_action( 'init', 'newspack_blocks_register_homepage_articles' ); |
| 440 | |
| 441 | |
| 442 | /** |
| 443 | * Renders author avatar markup. |
| 444 | * |
| 445 | * @param array $author_info Author info array. |
| 446 | * |
| 447 | * @return string Returns formatted Avatar markup |
| 448 | */ |
| 449 | function newspack_blocks_format_avatars( $author_info ) { |
| 450 | $elements = array_map( |
| 451 | function ( $author ) { |
| 452 | return sprintf( |
| 453 | '<a href="%s">%s</a>', |
| 454 | esc_url( $author->url ), |
| 455 | wp_kses( |
| 456 | $author->avatar, |
| 457 | Newspack_Blocks::get_sanitized_image_attributes() |
| 458 | ) |
| 459 | ); |
| 460 | }, |
| 461 | $author_info |
| 462 | ); |
| 463 | |
| 464 | return implode( '', $elements ); |
| 465 | } |
| 466 | |
| 467 | /** |
| 468 | * Renders byline markup. |
| 469 | * |
| 470 | * @param object[] $author_info Author info array. |
| 471 | * |
| 472 | * @return string Returns byline markup. |
| 473 | */ |
| 474 | function newspack_blocks_format_byline( $author_info ) { |
| 475 | $index = -1; |
| 476 | $elements = array_merge( |
| 477 | [ |
| 478 | '<span class="author-prefix">' . esc_html_x( 'by', 'post author', 'jetpack-mu-wpcom' ) . '</span> ', |
| 479 | ], |
| 480 | array_reduce( |
| 481 | $author_info, |
| 482 | function ( $accumulator, $author ) use ( $author_info, &$index ) { |
| 483 | $index++; |
| 484 | $penultimate = count( $author_info ) - 2; |
| 485 | return array_merge( |
| 486 | $accumulator, |
| 487 | [ |
| 488 | sprintf( |
| 489 | /* translators: 1: author link. 2: author name. 3. variable seperator (comma, 'and', or empty) */ |
| 490 | '<span class="author vcard"><a class="url fn n" href="%1$s">%2$s</a></span>', |
| 491 | esc_url( $author->url ), |
| 492 | esc_html( $author->display_name ) |
| 493 | ), |
| 494 | ( $index < $penultimate ) ? ', ' : '', |
| 495 | ( count( $author_info ) > 1 && $penultimate === $index ) ? esc_html_x( ' and ', 'post author', 'jetpack-mu-wpcom' ) : '', |
| 496 | ] |
| 497 | ); |
| 498 | }, |
| 499 | [] |
| 500 | ) |
| 501 | ); |
| 502 | |
| 503 | $byline = implode( '', $elements ); |
| 504 | |
| 505 | /** |
| 506 | * Filters the byline markup. |
| 507 | * |
| 508 | * @param string $byline Byline markup. |
| 509 | * @param objcet[] $author_info Author info array. |
| 510 | */ |
| 511 | return apply_filters( 'newspack_blocks_post_byline', $byline, $author_info ); |
| 512 | } |
| 513 | |
| 514 | /** |
| 515 | * Renders category markup plus filter. |
| 516 | * |
| 517 | * @param string $post_id Post ID. |
| 518 | */ |
| 519 | function newspack_blocks_format_categories( $post_id ) { |
| 520 | $category = false; |
| 521 | // Use Yoast primary category if set. |
| 522 | if ( class_exists( 'WPSEO_Primary_Term' ) ) { |
| 523 | $primary_term = new WPSEO_Primary_Term( 'category', $post_id ); |
| 524 | $category_id = $primary_term->get_primary_term(); |
| 525 | if ( $category_id ) { |
| 526 | $category = get_term( $category_id ); |
| 527 | } |
| 528 | } |
| 529 | if ( ! $category ) { |
| 530 | $categories_list = get_the_category(); |
| 531 | if ( ! empty( $categories_list ) ) { |
| 532 | $category = $categories_list[0]; |
| 533 | } |
| 534 | } |
| 535 | |
| 536 | if ( ! is_a( $category, 'WP_Term' ) ) { |
| 537 | return ''; |
| 538 | } |
| 539 | |
| 540 | $category_link = get_category_link( $category->term_id ); |
| 541 | $category_formatted = esc_html( $category->name ); |
| 542 | |
| 543 | if ( ! empty( $category_link ) ) { |
| 544 | $category_formatted = '<a href="' . esc_url( $category_link ) . '">' . $category_formatted . '</a>'; |
| 545 | } |
| 546 | |
| 547 | return apply_filters( 'newspack_blocks_categories', $category_formatted ); |
| 548 | } |