How do I use <picture> element instead of <img> tags in WordPress post content having webP support?
-
14-04-2021 - |
문제
I am developing my custom theme and trying to figure out how to modify the default code for WordPress image inserted into the post content, so I could add support for webP format and have it within <picture>
element.
I generate .webp
images using cwebp
library on my server and PHP exec()
while image upload to the Media in WordPress Admin.
The code is:
function my_image_webp($meta, $id){
if(!isset($meta['sizes'])) {
return $meta['full'];
}
$upload_path = wp_upload_dir();
$path = $upload_path['basedir'];
// media upload direktorij
if(isset($path)){
$file = trailingslashit($upload_path['basedir'].'/').$meta['file'];
}else{
$file = trailingslashit($upload_path['path']).$meta['file'];
}
list($orig_type) = @getimagesize($file);
switch ($orig_type) {
case IMAGETYPE_PNG:
$png_image = preg_replace('/\\.[^.\\s]{3,4}$/', '', $file);
exec("cwebp ".$file." -o ".$png_image.".webp");
break;
case IMAGETYPE_JPEG:
$jpg_image = preg_replace('/\\.[^.\\s]{3,4}$/', '', $file);
exec("cwebp ".$file." -o ".$jpg_image.".webp");
break;
}
// return
wp_update_attachment_metadata($id, $meta);
return $meta;
}
}
add_filter('wp_generate_attachment_metadata','my_image_webp', 10, 2);
Currently, my post content has got <img>
element to display the thumbnail within <p>
tag, but the <img>
tag is a link <a>
which points to the full-size image.
Currently I have got this for full-size image in the post content:
<p>
<a href="http://www.example.com/wp-content/uploads/2018/11/image-full.jpg" itemprop="url" title="Some title">
<img alt="Alt tag of the image" class="alignnone size-full" src="http://www.example.com/wp-content/uploads/2018/11/image-thumb.jpg" width="940" height="529">
</a>
</p>
I am trying to modify it to get this as result:
<p>
<a href="http://www.example.com/wp-content/uploads/2018/11/image-full.jpg" itemprop="url" title="Some title">
<picture>
<source srcset="http://www.example.com/wp-content/uploads/2018/11/image-thumb.webp" type="image/webp" />
<img alt="Alt tag of the image" class="alignnone size-full" src="http://www.example.com/wp-content/uploads/2018/11/image-thumb.jpg" width="940" height="529">
</picture>
</a>
</p>
I have one or more images inserted like this. So, would need to check the whole post content and somehow modify/replace this?
Should I use some preg_replace() or WordPress image_send_to_editor() function?
Maybe using some filter?
Do you have any ideas how to change it?
I have found some solutions for <figure>
element, but cannot get it working with <picture>
.
해결책
You have to loop through all images inside $post
the_content()
using foreach()
.
Which gives us, regex
for group matching of <img>
tag. Put all images into array()
.
Start counting from -1
since 0
has the 1st image already in array()
.
Loop through array()
with images, find image with "size-full"
with group match 3
, if yes, get it's src
value with group match 7
.
After, replace src="value"
extenstion - .png, .jpg ..., assign the replaced string to new variable. Use the new variable and add extension ".webp"
to the it.
Replace existing <img>
tags with <picture>
element and call the function on $content
.
function webp_picture_fix($content){
global $post;
preg_match_all("/<img(.*?)class=('|\")(.*?)('|\")(.*?)src=('|\")(.*?)('|\")(.*?)>/i", $content, $images);
if(!is_null($images)){
$i = -1;
foreach ($images as $key) {
$i++;
//echo $key[$i];
if(strpos($images[3][$i], 'size-full') !== false){
//echo "hi";
$slika_ekstenzija = $images[7][$i];
$sewebp = preg_replace('/\\.[^.\\s]{3,4}$/', '', $slika_ekstenzija);
$webp_slika_src = $sewebp.".webp";
$replacement = '<picture><source srcset="'.$webp_slika_src.'" type="image/webp" /><img'.$images[1][$i].'class='.$images[2][$i].$images[3][$i].$images[4][$i].$images[5][$i].'src='.$images[6][$i].$images[7][$i].$images[8][$i].$images[9][$i].'></picture>';
$content = str_replace($images[0][$i], $replacement, $content);
}
}
}
return $content;
}
add_filter('the_content', 'webp_picture_fix', 9999);