Skip to content

Instantly share code, notes, and snippets.

@vralle
Last active June 29, 2022 15:04
Show Gist options
  • Save vralle/f45d68d758e2d26e54b99b71fa13f5e4 to your computer and use it in GitHub Desktop.
Save vralle/f45d68d758e2d26e54b99b71fa13f5e4 to your computer and use it in GitHub Desktop.
Dynamic SVG sizes for safe-svg WP plugin
<?php
add_action('init', removeSafeSvgOnePixelFix');
function removeSafeSvgOnePixelFix()
{
global $wp_filter;
if (! class_exists('safe_svg')) {
return;
}
if (! isset($wp_filter['wp_get_attachment_image_src']->callbacks[10])) {
return;
}
$look_in = $wp_filter['wp_get_attachment_image_src']->callbacks[10];
foreach ($look_in as $callback) {
if (! is_array($callback['function'])) {
continue;
}
$object = $callback['function'][0] ?? null;
$method = $callback['function'][1] ?? null;
if ($object instanceof \safe_svg && $method === 'one_pixel_fix') {
remove_filter('wp_get_attachment_image_src', [$object, 'one_pixel_fix'], 10);
return;
}
}
}
// Removes sizes in SVG metadata
add_filter('wp_generate_attachment_metadata', 'filterMetadata', 11, 2);
/**
* Filters the generated attachment meta data.
*
* @param array<string,mixed> $metadata An array of attachment meta data.
* @param int $attachment_id Current attachment ID.
*
* @return array<string,mixed> $metadata
*/
function filterMetadata(array $metadata, int $attachment_id): array
{
$mime = get_post_mime_type($attachment_id);
if ($mime === 'image/svg+xml') {
// Removes unnecessary sizes for SVG (
// Generates by safe_svg::skip_svg_regeneration();
if (array_key_exists('sizes', $metadata)) {
unset($metadata['sizes']);
}
}
return $metadata;
}
// Generate size on request
add_filter('image_downsize', 'returnSvgSizes', 10, 3);
/**
* Filters whether to preempt the output of image_downsize().
*
* Returning a truthy value from the filter will effectively short-circuit
* down-sizing the image, returning that value instead.
*
* @param bool|array $downsize Whether to short-circuit the image downsize.
* @param int $id Attachment ID for image.
* @param string|int[] $size Requested image size. Can be any registered image size name, or
* an array of width and height values in pixels (in that order).
*/
function returnSvgSizes($downsize, $id, $size)
{
$mime = get_post_mime_type($id);
if ($mime !== 'image/svg+xml') {
return $downsize;
}
// This is where we need to get the dimensions. If they are not present, it will lead to unpredictable behavior.
// For control, we can use a metadata filter.
$meta = wp_get_attachment_metadata($id);
if (! $meta) {
return $downsize;
}
// 300x150 - Default size for <img>, <object>, <iframe> and inline <svg>
$file_width = $meta['width'] ?: 300;
$file_height = $meta['height'] ?: 150;
$file_url = wp_get_attachment_url($id);
// Custom handler for getting file url?
if (! $file_url) {
return $downsize;
}
$ratio = $file_width / $file_height;
if (is_array($size)) {
$width = $size[0];
$height = $size[1];
} else {
$additional_sizes = wp_get_additional_image_sizes();
if (isset($additional_sizes[$size])) {
$width = $additional_sizes[$size]['width'];
$height = $additional_sizes[$size]['height'];
} else {
$width = $file_width;
$height = $file_height;
}
}
// Responsive: width or height are zero
$width = $width ?: $height * $ratio;
$height = $height ?: $width / $ratio;
// Zero size: width and height are zero
$width = $width ?: $file_width;
$height = $height ?: $file_height;
$is_intermediate = ($size !== 'file');
return [$file_url, $width, $height, $is_intermediate];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment