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