1

I have this:

<img src="large/image.png" />

I want this:

<picture>
  <source media="(min-width:800px)" srcset="medium/image.png">
  <source media="(min-width:300px)" srcset="small/image.png">
  <img src="large/image.png" />
</picture>

I want to do it with PHP's DOMDocument and have tried this code: (there may be more than one image in the html)

$domContent = $domDocument->loadHTML($html);
$images = $domDocument->getElementsByTagName('img');
foreach ($images as $image) {
  $picture = $domDocument->createElement('picture');
  // $pic_clone = $picture->cloneNode();

  $source = $domDocument->createElement('source');
  $source->setAttribute("media", "(min-width:800px)");
  $source->setAttribute("srcset", "path_large");
  $source->setAttribute("media", "(min-width:300px)");
  $source->setAttribute("srcset", "path_small");

  $src_clone = $source->cloneNode();
  $src_clone->appendChild($picture);

  $image->parentNode->replaceChild($src_clone, $image);
  $src_clone->appendChild($image);
}

This produces:

<source media="(min-width:300px)" srcset="path_small">
<picture></picture>
<img src="large/image.png"></source>
  1. How to place the picture tag correctly?
  2. How do I get both source tags ?
  3. How can I avoid the closing source tag ?

I just cant wrap my head around this...

PS: Dont bother about the image paths, those I will fix later.

Hendrix
  • 11
  • 3
  • Does this answer your question? [How to wrap img element with a div tag](https://stackoverflow.com/questions/22131009/how-to-wrap-img-element-with-a-div-tag) – MaxiGui Oct 07 '20 at 13:39
  • Ehh, thats javascript (jquery) right? – Hendrix Oct 07 '20 at 14:50
  • Indeed, but the idea behind is quite similar, just write your html straight away and inject your img html in it. very simple... – MaxiGui Oct 07 '20 at 14:53
  • Problem is that I have a chunk of html with paragraphs, headings etc. including one or more images. – Hendrix Oct 07 '20 at 14:59

2 Answers2

0

you're appending it on source element instead of picture

replace this:

$src_clone = $source->cloneNode();
$src_clone->appendChild($picture);

$image->parentNode->replaceChild($src_clone, $image);
$src_clone->appendChild($image);

with this:

$src_clone = $source->cloneNode();
$picture->appendChild($src_clone);

$image->parentNode->replaceChild($src_clone, $image);
$picture->appendChild($image);
Sumit Wadhwa
  • 2,825
  • 1
  • 20
  • 34
  • No, that wont do it, now I end up with only the source tag: – Hendrix Oct 07 '20 at 13:36
  • @Hendrix I think you need to remove this line: `$image->parentNode->replaceChild($src_clone, $image);` what is the purpose of this line? – Sumit Wadhwa Oct 07 '20 at 13:39
  • I'm not quite sure. I adapted this code from a question here about wrapping a link. I will try out some more things and then I''l get back here later. Thanks for your input. – Hendrix Oct 07 '20 at 13:51
0

I got around to this code thanks to the hints from @swadhwa and @MaxiGui. Really appreciate your feedback, thanks.

private function PictureWrapper($content=false) {

    $domDocument = new DOMDocument();
    $domContent = $domDocument->loadHTML("<html><head><meta content='text/html; charset=utf-8' http-equiv='Content-Type'></head><body>" . $content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

    if (false === $domContent) {
        return $content;
    }
  
    $images = $domDocument->getElementsByTagName('img');
    if (0 === count($images)) {
        return $content;
    }

    foreach ($images as $image) {
        $img_src = $image->getAttribute("src");
        $arr = pathinfo($img_src);
        $dirname = $arr['dirname'];
        $base = $arr['basename'];

        $img_medium = $dirname . "/medium/" . $base;
        $img_small = $dirname . "/small/" . $base;

        $picture = $domDocument->createElement('picture');
        $pict_clone = $picture->cloneNode();
        $image->parentNode->replaceChild($pict_clone, $image);
        $pict_clone->appendChild($image);
            
        $source = $domDocument->createElement('source');
        $source->setAttribute("media", "(min-width:800px)");
        $source->setAttribute("srcset", $img_medium);
        $src_clone = $source->cloneNode();
        $image->parentNode->replaceChild($src_clone, $image);
        $src_clone->appendChild($image);
            
        $source = $domDocument->createElement('source');
        $source->setAttribute("media", "(min-width:300px)");
        $source->setAttribute("srcset", $img_small);
        $src_clone = $source->cloneNode();
        $image->parentNode->replaceChild($src_clone, $image);
        $src_clone->appendChild($image);
    }
    $content = $domDocument->saveHTML();
    $content = str_replace('<html><head><meta content="text/html; charset=utf-8" 
    http-equiv="Content-Type"></head><body>', "", $content);
    $content = str_replace('</body></html>', "", $content);
    $content = str_replace('</source>', "", $content);

    return $content;
}
Hendrix
  • 11
  • 3
  • This is my final solution, but I don't know how to close the question? edit: Oh, I can close/accept it tomorrow :o) – Hendrix Oct 08 '20 at 08:44
  • 1
    You accpt your own awnser. The question always remains open, unless closed for future refernces. – Dorvalla Oct 08 '20 at 08:45