Skip to content

Instantly share code, notes, and snippets.

@sophy
Forked from crstauf/class.image-tag.php
Created August 17, 2022 03:48
Show Gist options
  • Select an option

  • Save sophy/9c7043e86324fda0b3ee4b01c23da6d3 to your computer and use it in GitHub Desktop.

Select an option

Save sophy/9c7043e86324fda0b3ee4b01c23da6d3 to your computer and use it in GitHub Desktop.
A PHP class used to generate an <img> tag, specifically for use within WordPress sites (uploaded images, theme images, and external images) and the awesome lazysizes script (but not necessary).
<?php
class img_tag {
const DATAURI = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
var $url = false,
$image = false,
$image_id = false,
$alt = false,
$title = false,
$width = false,
$height = false,
$preload = false,
$sizes = 'auto',
$output = '',
$echo = true,
$lazy = true,
$noscript = true,
$first = array(),
$classes = array(),
$attributes = array(),
$image_sizes = array(),
$image_hires_sizes = array();
private $tag = array();
private $files = array();
private $done_output = false;
private $doing_noscript = false; // generating noscript image tag
function __construct($args) {
if (array_key_exists('theme_image',$args))
$args['url'] = get_stylesheet_directory_uri() . '/img/' . $args['theme_image'];
if (array_key_exists('url',$args))
$this->url = $args['url'];
else if (
array_key_exists('image_id',$args) &&
is_numeric($args['image_id'])
)
$this->image_id = $args['image_id'];
else
return false;
foreach ($args as $k => $v)
$this->$k = $v;
}
function __destruct() {
if (true === $this->done_output) return;
if (true === $this->echo) $this->display();
}
function output() {
if (false !== $this->image_id)
$generated = $noscript = $this->generate_from_id();
else
$generated = $noscript = $this->generate_from_url();
$generated['class'][] = $noscript['class'][] = 'generated-img-tag';
if (
array_key_exists('srcset',$generated) // multiple sizes of image available
&& (
$this->lazy || // loading image lazily
'auto' === $this->sizes // 'sizes' attribute is being set dynamically
)
) {
$generated['data-sizes'] = $generated['sizes'];
$generated['data-srcset'] = $generated['data-srcset-hires'] = $generated['srcset'];
unset($generated['sizes'],$generated['srcset']);
}
if (array_key_exists('srcset-hires',$generated)) {
$generated['data-srcset-hires'] = $generated['srcset-hires'];
$generated['class'][] = 'srcset-hires';
unset($generated['srcset-hires']);
}
if (true === $this->lazy) {
if (!array_key_exists('data-srcset',$generated))
$generated['data-src'] = $generated['src'];
$generated['src'] = self::DATAURI;
}
if (true === $this->noscript) {
$generated['class'][] = 'hide-if-no-js';
if ('auto' === $this->sizes)
unset($noscript['sizes'],$noscript['srcset']);
if (array_key_exists('id',$noscript))
$noscript['id'] .= '-noscript';
}
if (
array_key_exists('data-src',$generated) ||
array_key_exists('data-sizes',$generated)
)
$generated['class'][] = 'lazyload';
if (true === $this->preload)
$generated['class'][] = 'lazypreload';
$output = $this->generate_output($generated);
if (false !== $this->image_id)
$noscript['src'] = $this->files['__largest']['src'];
foreach ($noscript['class'] as $i => $class)
if (
(
'size-' === substr($class,0,5) &&
substr($class,5) !== $this->files['__largest']['name']
) ||
'attachment-' === substr($class,0,11)
)
unset($noscript['class'][$i]);
if (false !== $this->image_id)
$noscript['class'][] = 'attachment-' . $this->files['__largest']['name'];
if (true === $this->noscript) $output .= '<noscript>' . $this->generate_output($noscript,true) . '</noscript>' . "\n";
return $output;
}
function generate_output($attributes,$noscript = false) {
$output[] = '<img';
$output[] = 'src="' . $attributes['src'] . '"';
unset($attributes['src']);
if (array_key_exists('data-src',$attributes)) {
$output[] = 'data-src="' . $attributes['data-src'] . '"';
unset($attributes['data-src']);
}
$output[] = (array_key_exists('id',$attributes) ? 'id="' . $attributes['id'] . '" ' : '') .
'title="' . $attributes['title'] . '" ' .
'alt="' . $attributes['alt'] . '"';
unset($attributes['title'],$attributes['alt']);
$output[] = 'class="' . implode(' ',$attributes['class']) . '"';
unset($attributes['class']);
$output[] = 'width="' . $attributes['width'] . '" height="' . $attributes['height'] . '"' .
(array_key_exists('data-sizes',$attributes) && 'auto' === $attributes['data-sizes'] ? ' data-sizes="' . $attributes['data-sizes'] . '"' : '');
unset($attributes['width'],$attributes['height']);
if (array_key_exists('data-sizes',$attributes) && 'auto' === $attributes['data-sizes'])
unset($attributes['data-sizes']);
$sep = ", \n\t\t" . (true === $noscript ? "\t" : '');
foreach (array(
'data-srcset-hires',
'data-srcset',
'data-sizes',
'srcset',
'sizes'
) as $var)
if (array_key_exists($var,$attributes)) {
$output[] = $var . '="' . implode($sep,$attributes[$var]) . '"';
unset($attributes[$var]);
}
foreach ($attributes as $attrib => $value) {
$output[] = $attrib . '="' . (is_array($value) ? implode(' ',$value) : $value) . '"';
unset($attributes[$attrib]);
}
$sep = " \n\t" . (true === $noscript ? "\t" : '');
return "\n" . (true === $noscript ? "\t" : '') . implode($sep,$output) . " \n" . (true === $noscript ? "\t" : '') . '/>' . "\n";
}
function display() { echo $this->output(); }
function generate_from_id() {
if (false === $this->image)
$this->image = get_post($this->image_id);
if (false === $this->image_sizes)
$this->image_sizes = array('full');
else if (!is_array($this->image_sizes))
$this->image_sizes = (array) $this->image_sizes;
if (is_array($this->image_sizes) && 0 === count($this->image_sizes))
$this->image_sizes = array('medium','medium_large','large','full');
if (0 === count($this->first)) {
$this->first = wp_get_attachment_image_src($this->image_id,$this->image_sizes[0]);
$this->width = $this->first[1];
$this->height = $this->first[2];
}
if (false === $this->url)
$this->url = $this->first[0];
$attributes = array(
'src' => $this->first[0],
'title' => false === $this->title ? get_the_title($this->image) : $this->title,
'alt' => false === $this->alt ? $this->image->post_content : $this->alt,
'width' => $this->first[1],
'height' => $this->first[2],
'class' => array(
'attachment-' . $this->image_id,
'attachment-' . $this->image_sizes[0],
)
);
if (false === $this->alt)
$attributes['alt'] = ('' === $this->image->post_content ? $attributes['title'] : apply_filters('get_the_content',strip_tags($this->image->post_content)));
if (
1 < count($this->image_sizes) // multiple image sizes for 'srcset'
&& (
false === $this->doing_noscript || // not creating noscript image tag
'auto' !== $this->sizes // creating noscript image tag, but 'sizes' tag is not dynamic
)
) {
$this->files['__largest'] = array(
'width' => 0,
'src' => self::DATAURI,
);
$this->files['__smallest'] = array(
'width' => 9999999,
'src' => self::DATAURI,
);
if (true === $this->image_hires_sizes)
$this->image_hires_sizes = array('medium','medium_large','large','full');
foreach (array(
'srcset' => 'image_sizes',
'srcset-hires' => 'image_hires_sizes',
) as $attribute => $var)
if (is_array($this->{$var}) && count($this->{$var}))
foreach ($this->{$var} as $k => $size) {
if ('full' !== $size && false === image_get_intermediate_size($this->image_id,$size)) {
unset($this->{$var}[$k]);
continue;
}
$attributes['class'][] = 'size-' . $size;
if (array_key_exists($size,$this->files)) {
$this_size = $this->files[$size];
$mq = $k;
if (!is_string($k)) {
$mq = $this_size[1];
if ('srcset-hires' === $attribute)
$mq = round($mq / 2);
$mq .= 'w';
}
$attributes[$attribute][$this_size[1] . 'x' . $this_size[2]] = $this_size[0] . ' ' . $mq;
unset($this_size);
continue;
}
$src = $this->files[$size] = wp_get_attachment_image_src($this->image_id,$size);
$mq = $k;
if (!is_string($k)) {
$mq = $src[1];
if ('srcset-hires' === $attribute)
$mq = round($mq / 2);
$mq .= 'w';
}
$attributes[$attribute][$src[1] . 'x' . $src[2]] = $src[0] . ' ' . $mq;
if (intval($src[1]) > $this->files['__largest']['width'])
$this->files['__largest'] = array(
'width' => intval($src[1]),
'name' => $size,
'src' => $src[0],
);
if (intval($src[1]) < $this->files['__smallest']['width'])
$this->files['__smallest'] = array(
'width' => intval($src[1]),
'name' => $size,
'src' => $src[0],
);
}
if (array_key_exists('srcset',$attributes))
$attributes['sizes'] = $this->sizes;
}
$attributes['class'] = array_unique(array_merge($attributes['class'],$this->classes));
if (is_array($this->attributes) && count($this->attributes)) // merge passed attributes into tag
$attributes = array_merge($attributes,$this->attributes);
return $this->tag = $attributes;
}
function generate_from_url() {
if (false === $this->image)
$this->image = @getimagesize($this->url);
$attributes = array(
'src' => $this->url,
'title' => false !== $this->title ? $this->title : '',
'alt' => false !== $this->alt ? $this->alt : '',
'width' => false !== $this->width ? $this->width : (false !== $this->image ? $this->image[0] : false),
'height' => false !== $this->height ? $this->height : (false !== $this->image ? $this->image[1] : false),
'class' => $this->classes,
);
if (is_array($this->attributes) && count($this->attributes)) // merge passed attributes into tag
$attributes = array_merge($attributes,$this->attributes);
return $attributes;
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment