absint( $width ),
'height' => absint( $height ),
'srcset' => wp_calculate_image_srcset( $size_array, $src, $image_meta, $attachment_id ),
'sizes' => IMAGE_BREAKPOINTS,
'title' => get_the_title( $attachment_id ),
'alt' => get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ),
'caption' => wp_get_attachment_caption( $attachment_id ),
)
);
}
/**
* Enrich video information with extra data we can retrieve from the media library.
* Add missing `width`, `height`, `alt`, `url`, `title`, `caption` and `poster` properties to the image.
*
* @param array $media_file - An array containing the media attributes for a specific video.
*
* @return array $media_file_enriched
*/
function enrich_video_meta( $media_file ) {
$attachment_id = $media_file['id'] ?? null;
$video_meta = wp_get_attachment_metadata( $attachment_id );
if ( ! $video_meta ) {
return $media_file;
}
$video_url = ! empty( $video_meta['original']['url'] ) ? $video_meta['original']['url'] : wp_get_attachment_url( $attachment_id );
// Set the poster attribute for the video tag if a poster image is available.
$poster_url = null;
if ( ! empty( $video_meta['videopress']['poster'] ) ) {
$poster_url = $video_meta['videopress']['poster'];
} elseif ( ! empty( $video_meta['thumb'] ) ) {
$poster_url = str_replace( wp_basename( $video_url ), $video_meta['thumb'], $video_url );
}
if ( $poster_url ) {
/*
* Use the global content width for thumbnail resize so we match the `w=` query parameter
* that jetpack is going to add when "Enable site accelerator" is enabled for images.
*/
$content_width = (int) Jetpack::get_content_width();
$new_width = $content_width > 0 ? $content_width : EMBED_SIZE[0];
$poster_url = add_query_arg( 'w', $new_width, $poster_url );
}
return array_merge(
$media_file,
array(
'width' => absint( ! empty( $video_meta['width'] ) ? $video_meta['width'] : ( $media_file['width'] ?? 0 ) ),
'height' => absint( ! empty( $video_meta['height'] ) ? $video_meta['height'] : ( $media_file['height'] ?? 0 ) ),
'alt' => ! empty( $video_meta['videopress']['description'] ) ? $video_meta['videopress']['description'] : ( $media_file['alt'] ?? '' ),
'url' => $video_url,
'title' => get_the_title( $attachment_id ),
'caption' => wp_get_attachment_caption( $attachment_id ),
'poster' => $poster_url,
)
);
}
/**
* Render an image inside a slide
*
* @param array $media - Image information.
*
* @return string
*/
function render_image( $media ) {
$src = '';
$width = null;
$height = null;
if ( empty( $media['id'] ) || empty( $media['url'] ) ) {
return __( 'Error retrieving media', 'jetpack' );
}
$image = wp_get_attachment_image_src( $media['id'], 'full', false );
if ( $image ) {
list( $src, $width, $height ) = $image;
}
// if image does not match.
if ( ! $image || isset( $media['url'] ) && ! is_same_resource( $media['url'], $src ?? '' ) ) {
$width = $media['width'] ?? null;
$height = $media['height'] ?? null;
$title = $media['title'] ?? '';
$alt = $media['alt'] ?? '';
return sprintf(
'',
esc_attr( $title ),
esc_attr( $alt ),
$width && $height ? get_image_crop_class( $width, $height ) : '',
esc_attr( $media['url'] )
);
}
$crop_class = get_image_crop_class( $width, $height );
/*
* need to specify the size of the embed so it picks an image that is large enough for the `src` attribute
* `sizes` is optimized for 1080x1920 (9:16) images
* Note that the Story block does not have thumbnail support, it will load the right
* image based on the viewport size only.
*/
return wp_get_attachment_image(
$media['id'],
EMBED_SIZE,
false,
array(
'class' => sprintf( 'wp-story-image wp-image-%d %s', $media['id'], $crop_class ),
'sizes' => IMAGE_BREAKPOINTS,
'title' => get_the_title( $media['id'] ),
)
);
}
/**
* Return the css crop class if image width and height requires it
*
* @param int $width - Image width.
* @param int $height - Image height.
*
* @return string The CSS class which will display a cropped image
*/
function get_image_crop_class( $width, $height ) {
$crop_class = '';
$width = (int) $width;
$height = (int) $height;
if ( ! $width || ! $height ) {
return $crop_class;
}
$media_aspect_ratio = $width / $height;
$target_aspect_ratio = EMBED_SIZE[0] / EMBED_SIZE[1];
if ( $media_aspect_ratio >= $target_aspect_ratio ) {
// image wider than canvas.
$media_too_wide_to_crop = $media_aspect_ratio > $target_aspect_ratio / ( 1 - CROP_UP_TO );
if ( ! $media_too_wide_to_crop ) {
$crop_class = 'wp-story-crop-wide';
}
} else {
// image narrower than canvas.
$media_too_narrow_to_crop = $media_aspect_ratio < $target_aspect_ratio * ( 1 - CROP_UP_TO );
if ( ! $media_too_narrow_to_crop ) {
$crop_class = 'wp-story-crop-narrow';
}
}
return $crop_class;
}
/**
* Returns a URL for the site icon.
*
* @param int $size - Size for (square) sitei icon.
* @param string $fallback - Fallback URL to use if no site icon is found.
*
* @return string
*/
function get_blavatar_or_site_icon_url( $size, $fallback ) {
$image_array = Images::from_blavatar( get_the_ID(), $size );
if ( ! empty( $image_array ) ) {
return $image_array[0]['src'];
} else {
return $fallback;
}
}
/**
* Render a video inside a slide
*
* @param array $media - Video information.
*
* @return string
*/
function render_video( $media ) {
if ( empty( $media['id'] ) || empty( $media['mime'] ) || empty( $media['url'] ) ) {
return __( 'Error retrieving media', 'jetpack' );
}
if ( ! empty( $media['poster'] ) ) {
return render_image(
array_merge(
$media,
array(
'type' => 'image',
'url' => $media['poster'],
)
)
);
}
return sprintf(
'',
esc_attr( get_the_title( $media['id'] ) ),
esc_attr( $media['mime'] ),
absint( $media['id'] ),
esc_attr( $media['url'] )
);
}
/**
* Pick a thumbnail to render a static/embedded story
*
* @param array $media_files - list of Media files.
*
* @return string
*/
function render_static_slide( $media_files ) {
$media_template = '';
if ( empty( $media_files ) ) {
return '';
}
// find an image to showcase.
foreach ( $media_files as $media ) {
switch ( $media['type'] ) {
case 'image':
$media_template = render_image( $media );
break 2;
case 'video':
// ignore videos without a poster image.
if ( empty( $media['poster'] ) ) {
continue 2;
}
$media_template = render_video( $media );
break 2;
}
}
// if no "static" media was found for the thumbnail try to render a video tag without poster.
if ( empty( $media_template ) ) {
// enrich_media_files() may return an array with no zero-index, so use reset()
$media_template = render_video( reset( $media_files ) );
}
return sprintf(
'