'rest_sanitize_boolean', 'type' => 'boolean', 'description' => __( 'Whether the attachment is a poster image.', 'amp' ), 'show_in_rest' => true, 'single' => true, 'object_subtype' => 'attachment', ] ); // Used for amp-story[poster-portrait-src]: The story poster in portrait format (3x4 aspect ratio). add_image_size( self::STORY_CARD_IMAGE_SIZE, self::STORY_SMALL_IMAGE_DIMENSION, self::STORY_LARGE_IMAGE_DIMENSION, true ); // Used for amp-story[poster-square-src]: The story poster in square format (1x1 aspect ratio). add_image_size( self::STORY_SQUARE_IMAGE_SIZE, self::STORY_LARGE_IMAGE_DIMENSION, self::STORY_LARGE_IMAGE_DIMENSION, true ); // Used for amp-story[poster-landscape-src]: The story poster in square format (1x1 aspect ratio). add_image_size( self::STORY_LANDSCAPE_IMAGE_SIZE, self::STORY_LARGE_IMAGE_DIMENSION, self::STORY_SMALL_IMAGE_DIMENSION, true ); // The default image size for AMP Story image block and background media image. add_image_size( self::MAX_IMAGE_SIZE_SLUG, 99999, 1280 ); // Include additional story image sizes in Schema.org metadata. add_filter( 'amp_schemaorg_metadata', [ __CLASS__, 'filter_schemaorg_metadata_images' ], 100 ); // In case there is no featured image for the poster-portrait-src, add a fallback image. add_filter( 'wp_get_attachment_image_src', [ __CLASS__, 'poster_portrait_fallback' ], 10, 3 ); // If the image is for a poster-square-src or poster-landscape-src, this ensures that it's not too small. add_filter( 'wp_get_attachment_image_src', [ __CLASS__, 'ensure_correct_poster_size' ], 10, 3 ); add_filter( 'image_size_names_choose', [ __CLASS__, 'add_new_max_image_size' ] ); // The AJAX handler for when an image is cropped and sent via POST. add_action( 'wp_ajax_custom-header-crop', [ __CLASS__, 'crop_featured_image' ] ); add_action( 'pre_get_posts', [ __CLASS__, 'filter_poster_attachments' ] ); add_action( 'rest_api_init', [ __CLASS__, 'rest_api_init' ] ); } /** * Get story meta images. * * There is a fallback poster-portrait image added via a filter, in case there's no featured image. * * @since 1.2.1 * @see AMP_Story_Media::poster_portrait_fallback() * * @param int|WP_Post|null $post Post. * @return string[] Images. */ public static function get_story_meta_images( $post = null ) { $thumbnail_id = get_post_thumbnail_id( $post ); $images = [ 'poster-portrait' => wp_get_attachment_image_url( $thumbnail_id, self::STORY_CARD_IMAGE_SIZE ), 'poster-square' => wp_get_attachment_image_url( $thumbnail_id, self::STORY_SQUARE_IMAGE_SIZE ), 'poster-landscape' => wp_get_attachment_image_url( $thumbnail_id, self::STORY_LANDSCAPE_IMAGE_SIZE ), ]; return array_filter( $images ); } /** * Include additional story image sizes in Schema.org metadata for AMP Stories. * * @since 1.2.1 * * @param array $data Metadata. * @return array Metadata. */ public static function filter_schemaorg_metadata_images( $data ) { if ( ! is_singular( AMP_Story_Post_Type::POST_TYPE_SLUG ) ) { return $data; } if ( empty( $data['image'] ) ) { $data['image'] = []; } elseif ( is_string( $data['image'] ) ) { $data['image'] = [ $data['image'] ]; } elseif ( is_array( $data['image'] ) && isset( $data['image']['@type'] ) ) { $data['image'] = [ $data['image'] ]; } elseif ( ! is_array( $data['image'] ) ) { $data['image'] = []; } $data['image'] = array_merge( array_values( self::get_story_meta_images() ), $data['image'] ); return $data; } /** * If there's no featured image for the poster-portrait-src, this adds a fallback. * * @param array|false $image The featured image, or false. * @param int $attachment_id The ID of the image. * @param string|array $size The size of the image. * @return array|false The featured image, or false. */ public static function poster_portrait_fallback( $image, $attachment_id, $size ) { if ( ! $image && self::STORY_CARD_IMAGE_SIZE === $size ) { return [ amp_get_asset_url( 'images/stories-editor/story-fallback-poster.jpg' ), self::STORY_LARGE_IMAGE_DIMENSION, self::STORY_SMALL_IMAGE_DIMENSION, ]; } return $image; } /** * Helps to ensure that the poster-square-src and poster-landscape-src images aren't too small. * * These values come from the featured image. * But the featured image is often cropped down to 696 x 928. * So from that, it's not possible to get a 928 x 928 image, for example. * So instead, use the source image that was cropped, instead of the cropped image. * This is more likely to produce the right size image. * * @param array|false $image The featured image, or false. * @param int $attachment_id The ID of the image. * @param string|array $size The size of the image. * @return array|false The featured image, or false. */ public static function ensure_correct_poster_size( $image, $attachment_id, $size ) { if ( self::STORY_LANDSCAPE_IMAGE_SIZE === $size || self::STORY_SQUARE_IMAGE_SIZE === $size ) { $attachment_meta = wp_get_attachment_metadata( $attachment_id ); // The source image that was cropped. if ( ! empty( $attachment_meta['attachment_parent'] ) ) { return wp_get_attachment_image_src( $attachment_meta['attachment_parent'], $size ); } } return $image; } /** * Adds a new max image size to the image sizes available. * * This filter makes this custom image size available in the Image block's 'Image Size'