Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
demountable
/
wp-content
/
plugins
/
surerank
/
inc
/
frontend
:
image.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php /** * Image Meta Data * * Handles functionality to retrieve and manage image metadata for frontend requests, * particularly for Open Graph image tags. * * @package surerank * @since 0.0.1 */ namespace SureRank\Inc\Frontend; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } use SureRank\Inc\Functions\Settings; use SureRank\Inc\Meta_Variables\Post; use SureRank\Inc\Traits\Get_Instance; /** * Image Meta Data Handler * * Manages image metadata retrieval for frontend requests, optimized for Open Graph tags. * * @since 0.0.1 */ class Image { use Get_Instance; /** * Cache for image data * * @var array<string, string|null> */ private $image_cache = []; /** * Retrieves Open Graph image URL based on page type * * @return string|null OG image URL or null if none found * @since 1.0.0 */ public function get_og_image() { if ( post_password_required() ) { return null; } if ( ! get_queried_object_id() ) { return null; } $cache_key = md5( (string) wp_json_encode( get_queried_object_id() ) ); if ( isset( $this->image_cache[ $cache_key ] ) ) { return $this->image_cache[ $cache_key ]; } $image_url = null; if ( is_singular() ) { $image_url = $this->get_singular_page_image(); } elseif ( is_tax() || is_category() || is_tag() ) { $image_url = $this->get_taxonomy_image(); } $this->image_cache[ $cache_key ] = $image_url; return $image_url; } /** * Get attachment ID by URL * * @param string $url Image URL. * @return int Attachment ID or 0 if not found * @since 1.0.0 */ public function attachment_by_url( $url ) { $attachment_id = attachment_url_to_postid( $url ); return (int) $attachment_id; } /** * Prepare fallback image * * @param array<string, mixed> $meta_data Meta Data. * @param string $key Meta key to populate. * @since 1.0.0 * @return void */ public function get( &$meta_data, $key ) { $fallback_image = Settings::get( 'fallback_image' ); if ( ! empty( $meta_data[ $key ] ) ) { return; } if ( $this->get_og_image() ) { $meta_data[ $key ] = $this->get_og_image(); } else { $meta_data[ $key ] = $fallback_image; } } /** * Retrieves taxonomy page image * * @param int|null $term_id The term ID. * @return string|null Taxonomy image URL or null if none found * @since 1.0.0 */ public function get_taxonomy_image( $term_id = null ) { $term_description = ''; if ( ! $term_id ) { $term_description = term_description(); } else { $term_data = get_term( $term_id ); if ( $term_data ) { $term_description = $term_data->description ?? ''; } } if ( ! $term_description ) { return null; } return $this->get_first_content_image( $term_description ); } /** * Retrieves singular page image * * @param int|null $post_id The post ID. * @return string|null Singular page image URL or null if none found * @since 1.0.0 */ public function get_singular_page_image( $post_id = null ) { if ( ! $post_id ) { $post_id = get_queried_object_id(); } if ( ! $post_id ) { return null; } $post_instance = Post::get_instance(); $post_instance->set_post( $post_id ); $content = $post_instance->get_content(); return $content ? $this->get_first_content_image( $content ) : null; } /** * Extracts first valid image from content * * @param string $content The content to search. * @return string|null Image URL or null if none found * @since 1.0.0 */ private function get_first_content_image( string $content ) { if ( empty( $content ) || strpos( $content, '<img' ) === false ) { return null; } if ( ! preg_match( '/<img\s+[^>]*?src=["\']([^"\']+)["\']/i', $content, $match ) ) { return null; } $src = trim( $match[1] ); if ( empty( $src ) ) { return null; } $absolute_url = $this->ensure_absolute_url( $src ); $image_data = $this->get_image_data_by_url( $absolute_url ); return $image_data && $this->is_valid_og_image( $image_data ) ? $image_data['url'] : null; } /** * Gets image data by attachment ID * * @param int $attachment_id The attachment ID. * @return array<string, mixed>|null Image data array or null if invalid * @since 1.0.0 */ private function get_image_data_by_id( int $attachment_id ) { if ( ! wp_attachment_is_image( $attachment_id ) ) { return null; } $image = wp_get_attachment_image_src( $attachment_id, 'large' ); if ( ! $image ) { return null; } [$url, $width, $height] = $image; return [ 'id' => $attachment_id, 'url' => $url, 'width' => $width, 'height' => $height, 'type' => get_post_mime_type( $attachment_id ), 'alt' => get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ?? '', ]; } /** * Gets image data by URL * * @param string $url Image URL. * @return array<string, mixed>|null Image data array or null if invalid * @since 1.0.0 */ private function get_image_data_by_url( string $url ) { $url = filter_var( $url, FILTER_VALIDATE_URL ) ? $url : null; if ( ! $url ) { return null; } $attachment_id = $this->attachment_by_url( $url ); if ( $attachment_id > 0 ) { return $this->get_image_data_by_id( $attachment_id ); } if ( ! $this->is_valid_image_extension( $url ) ) { return null; } return [ 'url' => $url ]; } /** * Validates image for Open Graph use * * @param array<string, mixed> $image_data Image data to validate. * @return bool Whether image meets OG requirements * @since 1.0.0 */ private function is_valid_og_image( array $image_data ) { if ( empty( $image_data['url'] ) || ! $this->is_valid_image_extension( $image_data['url'] ) ) { return false; } if ( isset( $image_data['width'] ) && isset( $image_data['height'] ) ) { return $image_data['width'] >= apply_filters( 'surerank_og_dimensions_min_width', 200 ) && $image_data['height'] >= apply_filters( 'surerank_og_dimensions_min_height', 200 ) && $image_data['width'] <= apply_filters( 'surerank_og_dimensions_max_width', 2000 ) && $image_data['height'] <= apply_filters( 'surerank_og_dimensions_max_height', 2000 ); } return true; } /** * Validates image file extension * * @param string $url Image URL. * @return bool Whether extension is valid * @since 1.0.0 */ private function is_valid_image_extension( string $url ) { $valid_extensions = [ 'jpg', 'jpeg', 'png', 'gif', 'webp' ]; $extension = strtolower( pathinfo( $url, PATHINFO_EXTENSION ) ); return ! empty( $extension ) && in_array( $extension, $valid_extensions, true ); } /** * Ensures URL is absolute * * @param string $url Input URL. * @return string Absolute URL * @since 1.0.0 */ private function ensure_absolute_url( string $url ): string { if ( empty( $url ) ) { return ''; } $sanitized_url = filter_var( $url, FILTER_SANITIZE_URL ); if ( ! $sanitized_url ) { return ''; } return filter_var( $sanitized_url, FILTER_VALIDATE_URL ) ? $sanitized_url : home_url( $sanitized_url ); } }