Last active
September 21, 2025 11:54
-
-
Save Jehu/e69c8abd1386806b416e83422ed614b9 to your computer and use it in GitHub Desktop.
Etch Page Builder Integration for Image Background Focus Position Plugin - https://www.wordpress-focalpoint.com
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Etch Page Builder Integration for Image Background Focus Position Plugin | |
* | |
* This file provides compatibility between the Image Background Focus Position plugin | |
* and the Etch page builder. Add this code to your child theme's functions.php file. | |
* | |
* Requires: Image Background Focus Position plugin to be active: https://www.wordpress-focalpoint.com/ | |
* | |
* Add this file to /inc/ directory of your child theme | |
* Then add this code to the functions.php: | |
* | |
* $img_bg_position_file = get_stylesheet_directory() . '/inc/image-bg-position-support.php'; | |
* if (file_exists($img_bg_position_file)) { | |
* require_once $img_bg_position_file; | |
* } | |
* | |
*/ | |
// Prevent direct access | |
if (!defined('ABSPATH')) { | |
exit; | |
} | |
// Toggle to enable/disable image attribute enhancement | |
// Set to false to disable srcset, dimensions, alt, and sizes attribute addition | |
// set to true only, if you have https://gist.github.com/Jehu/c7211b626104aa5a46e189a15e9a2dd0 | |
define('ETCH_ENHANCE_IMAGE_ATTRIBUTES', false); | |
// Load standalone image enhancement if enabled | |
if (ETCH_ENHANCE_IMAGE_ATTRIBUTES) { | |
$etch_enhancement_file = __DIR__ . '/etch-image-enhancement.php'; | |
if (file_exists($etch_enhancement_file)) { | |
require_once $etch_enhancement_file; | |
} | |
} | |
// Add focus point data to attachment metadata | |
add_filter('wp_get_attachment_metadata', 'etch_add_focus_to_attachment_metadata', 10, 2); | |
// Add support for Etch page builder - hook AFTER Etch processes images | |
add_filter('render_block', 'etch_ibcp_filter_images', 15, 2); | |
/** | |
* Add focus point data to attachment metadata | |
*/ | |
function etch_add_focus_to_attachment_metadata($metadata, $attachment_id) | |
{ | |
if (!is_array($metadata)) { | |
$metadata = []; | |
} | |
$desktop = get_post_meta($attachment_id, 'bg_pos_desktop', true); | |
$mobile = get_post_meta($attachment_id, 'bg_pos_mobile', true); | |
if ($desktop || $mobile) { | |
$metadata['focus_point'] = [ | |
'desktop' => $desktop ?: '50% 50%', | |
'mobile' => $mobile ?: $desktop | |
]; | |
} | |
return $metadata; | |
} | |
/** | |
* Apply focus points to images in Etch blocks | |
*/ | |
function etch_ibcp_filter_images($block_content, $block) | |
{ | |
// Process etch/block blocks (which contain the actual images) | |
if ('etch/block' !== ($block['blockName'] ?? '')) { | |
return $block_content; | |
} | |
// Apply focus points to images in the block content | |
$block_content = preg_replace_callback( | |
'/<img([^>]+)src=["\']([^"\']*wp-content\/uploads[^"\']*)["\']([^>]*)>/i', | |
'etch_ibcp_add_focus_to_image', | |
$block_content | |
); | |
return $block_content; | |
} | |
/** | |
* Add focus point to individual Etch image | |
*/ | |
function etch_ibcp_add_focus_to_image($matches) | |
{ | |
$full_tag = $matches[0]; | |
$src = $matches[2]; | |
// Try to get attachment ID from src URL | |
$attachment_id = attachment_url_to_postid($src); | |
// If that fails, try a more comprehensive search | |
if (!$attachment_id) { | |
$attachment_id = etch_ibcp_find_attachment_by_filename($src); | |
} | |
if (!$attachment_id) { | |
return $full_tag; | |
} | |
// Get focus point data from attachment metadata | |
$metadata = wp_get_attachment_metadata($attachment_id); | |
$focus_point = $metadata['focus_point'] ?? null; | |
if (!$focus_point) { | |
return $full_tag; | |
} | |
// Determine which position to use | |
$position = wp_is_mobile() ? $focus_point['mobile'] : $focus_point['desktop']; | |
if (!$position || $position === '50% 50%') { | |
return $full_tag; | |
} | |
// Check if object-position is already applied | |
if (strpos($full_tag, 'object-position:') !== false) { | |
return $full_tag; // Already has focus point applied | |
} | |
// Add or modify style attribute | |
if (strpos($full_tag, 'style=') !== false) { | |
// Style attribute exists, append to it | |
$full_tag = preg_replace( | |
'/style=["\']([^"\']*)["\']/', | |
'style="$1; object-position: ' . $position . '"', | |
$full_tag | |
); | |
} else { | |
// No style attribute, add one | |
$full_tag = str_replace('<img', '<img style="object-position: ' . $position . '"', $full_tag); | |
} | |
// Enhance image with missing attributes if enabled and function exists | |
if (ETCH_ENHANCE_IMAGE_ATTRIBUTES && function_exists('etch_enhancement_add_attributes')) { | |
$full_tag = etch_enhancement_add_attributes($full_tag, $attachment_id); | |
} | |
return $full_tag; | |
} | |
/** | |
* Find attachment ID by searching for filename in database | |
*/ | |
function etch_ibcp_find_attachment_by_filename($src) | |
{ | |
global $wpdb; | |
// Extract filename from URL | |
$filename = basename($src); | |
// Remove size suffixes (e.g., -1440x960, -scaled, etc.) | |
$base_filename = preg_replace('/-\d+x\d+\./', '.', $filename); | |
$base_filename = preg_replace('/-scaled\./', '.', $base_filename); | |
// Also get the original filename without any suffix | |
$original_filename = preg_replace('/-[^.]*\./', '.', $filename); | |
// Search for attachments with matching filenames | |
$query = $wpdb->prepare( | |
"SELECT post_id FROM {$wpdb->postmeta} | |
WHERE meta_key = '_wp_attached_file' | |
AND (meta_value LIKE %s OR meta_value LIKE %s OR meta_value LIKE %s) | |
LIMIT 1", | |
'%' . $filename, | |
'%' . $base_filename, | |
'%' . $original_filename | |
); | |
$attachment_id = $wpdb->get_var($query); | |
if (!$attachment_id) { | |
// Try searching in the guid field as a last resort | |
$query = $wpdb->prepare( | |
"SELECT ID FROM {$wpdb->posts} | |
WHERE post_type = 'attachment' | |
AND guid LIKE %s | |
LIMIT 1", | |
'%' . $original_filename | |
); | |
$attachment_id = $wpdb->get_var($query); | |
} | |
return $attachment_id ? intval($attachment_id) : null; | |
} | |
/** | |
* Enhance image tag with missing attributes (srcset, dimensions, alt, sizes) | |
* Only adds attributes if they don't already exist (even if empty) | |
*/ | |
function etch_enhance_image_attributes($img_tag, $attachment_id) | |
{ | |
if (!ETCH_ENHANCE_IMAGE_ATTRIBUTES) { | |
return $img_tag; | |
} | |
// Get attachment metadata and post data | |
$metadata = wp_get_attachment_metadata($attachment_id); | |
$attachment = get_post($attachment_id); | |
if (!$metadata || !$attachment) { | |
return $img_tag; | |
} | |
$attributes_to_add = []; | |
// Extract dimensions from filename if present (e.g., my-image-1440x960.webp) | |
$src_url = ''; | |
if (preg_match('/src=["\']([^"\']*)["\']/', $img_tag, $src_matches)) { | |
$src_url = $src_matches[1]; | |
} | |
$width = null; | |
$height = null; | |
if ($src_url) { | |
$filename = basename($src_url); | |
if (preg_match('/-(\d+)x(\d+)\.[^.]+$/', $filename, $size_matches)) { | |
$width = intval($size_matches[1]); | |
$height = intval($size_matches[2]); | |
} | |
} | |
// Fallback to metadata dimensions if no size found in filename | |
if (!$width && isset($metadata['width'])) { | |
$width = $metadata['width']; | |
} | |
if (!$height && isset($metadata['height'])) { | |
$height = $metadata['height']; | |
} | |
// Add width if not present | |
if (strpos($img_tag, 'width=') === false && $width) { | |
$attributes_to_add[] = 'width="' . $width . '"'; | |
} | |
// Add height if not present | |
if (strpos($img_tag, 'height=') === false && $height) { | |
$attributes_to_add[] = 'height="' . $height . '"'; | |
} | |
// Add alt if not present | |
if (strpos($img_tag, 'alt=') === false) { | |
$alt_text = get_post_meta($attachment_id, '_wp_attachment_image_alt', true); | |
$alt_text = $alt_text ?: $attachment->post_title; | |
$attributes_to_add[] = 'alt="' . esc_attr($alt_text) . '"'; | |
} | |
// Add srcset if not present | |
if (strpos($img_tag, 'srcset=') === false) { | |
$srcset = wp_get_attachment_image_srcset($attachment_id); | |
if ($srcset) { | |
$attributes_to_add[] = 'srcset="' . esc_attr($srcset) . '"'; | |
} | |
} | |
// Add sizes if not present (and srcset was added) | |
if (strpos($img_tag, 'sizes=') === false && strpos($img_tag, 'srcset=') === false) { | |
$sizes = wp_get_attachment_image_sizes($attachment_id); | |
if ($sizes) { | |
$attributes_to_add[] = 'sizes="' . esc_attr($sizes) . '"'; | |
} | |
} | |
// Add all missing attributes to the img tag | |
if (!empty($attributes_to_add)) { | |
$attributes_string = ' ' . implode(' ', $attributes_to_add); | |
$img_tag = str_replace('<img', '<img' . $attributes_string, $img_tag); | |
} | |
return $img_tag; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment