Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save EricBusch/96dfe2ffb8fa6840793f3d2b1e1e9dbd to your computer and use it in GitHub Desktop.
Save EricBusch/96dfe2ffb8fa6840793f3d2b1e1e9dbd to your computer and use it in GitHub Desktop.
Replaces any placeholder images with hotlinked image from merchant's server. [dfrpswc][datafeedr]
<?php
/**
* Class Mycode_Replace_Missing_Images_With_External_Images
*
* Replaces any placeholder images with hotlinked image from merchant's server.
*
* @since 1.0.0
*/
class Mycode_Replace_Missing_Images_With_External_Images {
private $css_class = 'dfr-external-image';
private $max_width = '300px';
private $max_height = '300px';
private $image_fields = [ 'image', 'thumbnail' ];
public function init() {
add_action( 'wp_head', [ $this, 'add_css' ] );
add_filter( 'woocommerce_product_get_image', [ $this, 'get_image_tag_for_loop' ], 100, 2 );
add_filter( 'woocommerce_placeholder_img_src', [ $this, 'replace_placeholder_img_src' ], 20, 1 );
}
/**
* Add CSS to <head> element to handle clipping and sizing of external images.
*
* @link https://stackoverflow.com/a/51447865/2489248
*/
function add_css() {
echo '<style type="text/css">';
echo 'ul.products .' . $this->css_class . ' {position:relative;width:100%;margin-bottom:22.652px;} ';
echo 'ul.products .' . $this->css_class . ':after {content:"";display:block;padding-bottom:100%;} ';
echo 'ul.products .' . $this->css_class . ' img {position:absolute;top:0;bottom:0;left:0;right:0;width:100%;height:100%;object-fit:cover;object-position:center;max-width:' . $this->max_width . ';}';
echo '</style>';
}
/**
* Replace placeholder <img> tags inside WC Loop with <img> tag with src attribute
* of product's external image URL.
*
* @param string $image HTML string containing the full <img> tag markup.
* @param WC_Product $product
*
* @return string
*/
function get_image_tag_for_loop( $image, $product ) {
if ( ! preg_match( "/woocommerce-placeholder/i", $image ) ) {
return $image;
}
if ( empty( $dfr_product = dfrps_product( $product->get_id() ) ) ) {
return $image;
}
if ( ! $src = $this->get_external_image_src( $dfr_product ) ) {
return $image;
}
$attributes = [];
$attributes['width'] = absint( $this->max_width );
$attributes['height'] = absint( $this->max_height );
$attributes['src'] = esc_url( $src );
$attributes['class'] = 'attachment-woocommerce_thumbnail size-woocommerce_thumbnail';
$attributes['alt'] = esc_attr( $product->get_name() );
$format = '<div class="%1$s"><img %2$s /></div>';
return sprintf( $format, esc_attr( $this->css_class ), implode( ' ', array_map( function ( $k, $v ) {
return $k . '="' . $v . '"';
}, array_keys( $attributes ), $attributes ) ) );
}
/**
* Replace URL of placeholder image with the URL from the "image" field to
* hotlink the product image direct from merchant's server.
*
* @param string $src URL of default WooCommerce placeholder image.
*
* @return string URL The URL of the product image from the merchant's server.
*/
function replace_placeholder_img_src( $src ) {
/** @var WC_Product $product */
global $product;
if ( ! is_product() ) {
return $src;
}
if ( ! is_subclass_of( $product, 'WC_Product' ) ) {
return $src;
}
if ( empty( $dfr_product = dfrps_product( $product->get_id() ) ) ) {
return $src;
}
if ( $external_src = $this->get_external_image_src( $dfr_product ) ) {
$src = $external_src;
}
return $src;
}
/**
* Returns the first occurrence of an image field for the Datafeedr product
* or false if no image fields are found.
*
* @param array $product A full Datafeedr product array.
*
* @return bool|string
*/
private function get_external_image_src( $product ) {
foreach ( $this->image_fields as $field ) {
if ( isset( $product[ $field ] ) && $this->starts_with( $product[ $field ], [ 'http', '//' ] ) ) {
return $product[ $field ];
}
}
return false;
}
/**
* Determine if a given string starts with a given substring.
*
* @param string $haystack
* @param string|array $needles
*
* @return bool
*/
private function starts_with( $haystack, $needles ) {
foreach ( (array) $needles as $needle ) {
if ( $needle !== '' && substr( $haystack, 0, strlen( $needle ) ) === (string) $needle ) {
return true;
}
}
return false;
}
}
( new Mycode_Replace_Missing_Images_With_External_Images() )->init();
// EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment