Skip to content

Instantly share code, notes, and snippets.

@Jehu
Last active September 21, 2025 11:54
Show Gist options
  • Save Jehu/e69c8abd1386806b416e83422ed614b9 to your computer and use it in GitHub Desktop.
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
<?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