diff --git a/Image/Image.php b/Image/Image.php
index 81aa1ed..8840385 100644
--- a/Image/Image.php
+++ b/Image/Image.php
@@ -14,16 +14,24 @@ class Image
*/
private $url;
+ /**
+ * @var ?string
+ */
+ private $srcSet = null;
+
/**
* @param string $path
* @param string $url
+ * @param ?string $srcSet
*/
public function __construct(
string $path,
- string $url
+ string $url,
+ ?string $srcSet = null
) {
$this->path = $path;
$this->url = $url;
+ $this->srcSet = $srcSet;
}
/**
@@ -42,6 +50,22 @@ public function getUrl(): string
return $this->url;
}
+ /**
+ * @return ?string
+ */
+ public function getSrcSet(): ?string
+ {
+ return $this->srcSet;
+ }
+
+ /**
+ * @param ?string
+ */
+ public function setSrcSet(?string $srcSet): void
+ {
+ $this->srcSet = $srcSet;
+ }
+
/**
* @return string
*/
diff --git a/Image/ImageCollector.php b/Image/ImageCollector.php
index ab85aa8..5643e86 100644
--- a/Image/ImageCollector.php
+++ b/Image/ImageCollector.php
@@ -40,10 +40,10 @@ public function __construct(
}
/**
- * @param string $imageUrl
+ * @param string|array $imageUrl
* @return Image[]
*/
- public function collect(string $imageUrl): array
+ public function collect($imageUrl): array
{
try {
$image = $this->imageFactory->createFromUrl($imageUrl);
diff --git a/Image/ImageFactory.php b/Image/ImageFactory.php
index ca920ea..2336138 100644
--- a/Image/ImageFactory.php
+++ b/Image/ImageFactory.php
@@ -37,17 +37,35 @@ public function createFromPath(string $path): Image
}
/**
- * @param string $url
+ * @param array|string $url
* @return Image
* @throws FileSystemException
*/
- public function createFromUrl(string $url): Image
+ public function createFromUrl($url): Image
+ {
+ $urls = is_array($url) ? $url : [$url];
+ $baseUrl = $this->cleanUrl($urls[0] ?? '');
+ $srcSet = $this->getSrcSet($urls);
+ $path = $this->urlConvertor->getFilenameFromUrl($baseUrl);
+ return $this->objectManager->create(Image::class, ['path' => $path, 'url' => $baseUrl, 'srcSet' => $srcSet]);
+ }
+
+ private function cleanUrl(string $url): string
{
if (strpos($url, 'http') !== false) {
- $url = explode('?', $url)[0];
+ return explode('?', $url)[0];
}
-
- $path = $this->urlConvertor->getFilenameFromUrl($url);
- return $this->objectManager->create(Image::class, ['path' => $path, 'url' => $url]);
+
+ return $url;
+ }
+
+ private function getSrcSet(array $urls): string
+ {
+ $srcSetPieces = [];
+ foreach ($urls as $key => $url) {
+ $srcSetPieces[] = $this->cleanUrl($url) . ($key !== 0 ? (' ' . $key) : '');
+ }
+
+ return implode(',', $srcSetPieces);
}
}
diff --git a/Test/Unit/Image/ImageFactoryTest.php b/Test/Unit/Image/ImageFactoryTest.php
index 4d0496d..526552f 100644
--- a/Test/Unit/Image/ImageFactoryTest.php
+++ b/Test/Unit/Image/ImageFactoryTest.php
@@ -42,6 +42,26 @@ public function testCreateFromUrl()
$this->assertEquals('/foo/bar.jpg', $image->getUrl());
}
+ public function testCreateFromUrlWithMultipleUrls()
+ {
+ $urlConvertor = $this->getUrlConvertor();
+ $urlConvertor->method('getFilenameFromUrl')->willReturn('/tmp/pub/foo/bar.jpg');
+ $urlConvertor->method('getUrlFromFilename')->willReturn('/foo/bar.jpg');
+ $objectManager = $this->getObjectManager();
+ $objectManager->method('create')->willReturn(
+ new Image('/tmp/pub/foo/bar.jpg', '/foo/bar.jpg', '/foo/bar.jpg,/baz/qux.jpg 500w')
+ );
+
+ // @phpstan-ignore-next-line
+ $imageFactory = new ImageFactory($objectManager, $urlConvertor);
+ $image = $imageFactory->createFromUrl(['/foo/bar.jpg', '500w' => '/baz/qux.jpg']);
+
+ $this->assertInstanceOf(Image::class, $image);
+ $this->assertEquals('/tmp/pub/foo/bar.jpg', $image->getPath());
+ $this->assertEquals('/foo/bar.jpg', $image->getUrl());
+ $this->assertEquals('/foo/bar.jpg,/baz/qux.jpg 500w', $image->getSrcSet());
+ }
+
private function getObjectManager(): MockObject
{
return $this->getMockBuilder(ObjectManagerInterface::class)
diff --git a/Test/Unit/Image/ImageTest.php b/Test/Unit/Image/ImageTest.php
index 8881c4e..b8e7f2a 100644
--- a/Test/Unit/Image/ImageTest.php
+++ b/Test/Unit/Image/ImageTest.php
@@ -20,6 +20,12 @@ public function testGetUrl()
$this->assertEquals('/media/foobar.jpg', $image->getUrl());
}
+ public function testGetSrcSet()
+ {
+ $image = new Image('/tmp/pub/foobar.jpg', '/media/foobar.jpg', '/foo/bar.jpg,/baz/qux.jpg 500w');
+ $this->assertEquals('/foo/bar.jpg,/baz/qux.jpg 500w', $image->getSrcSet());
+ }
+
public function testGetMimetype()
{
$image = new Image('/tmp/pub/foobar.gif', 'foobar.gif');
diff --git a/Util/HtmlReplacer.php b/Util/HtmlReplacer.php
index afa32da..d9b6687 100644
--- a/Util/HtmlReplacer.php
+++ b/Util/HtmlReplacer.php
@@ -113,7 +113,7 @@ private function getImageHtmlFromImage(DOMElement $image, string $html): string
return '';
}
- $regex = '/
"]*)(?:"[^"]*"[^>"]*)*>/';
+ $regex = '/
]+)>/';
if (!preg_match($regex, $html, $imageHtmlMatch)) {
return '';
}
@@ -136,15 +136,35 @@ private function getPictureHtmlFromImage(DOMElement $image, string $html): strin
if (!$this->isAllowedByParentNode($image)) {
return '';
}
+
+ $imageSrcSet = $image->getAttribute('srcset');
+ if ($imageSrcSet) {
+ $srcSetImages = explode(',', $imageSrcSet);
+ $imageUrls = [];
+ foreach ($srcSetImages as $srcSetImage) {
+ $pieces = explode(' ', trim($srcSetImage));
+ if (isset($pieces[1])) {
+ $descriptor = $pieces[1];
+ $imageUrls[$descriptor] = $pieces[0];
+ } else {
+ $descriptor = 0;
+ $imageUrl = $imageUrls[$descriptor] = $pieces[0];
+ }
+ }
+ $images = $this->imageCollector->collect($imageUrls);
+ if (!count($images) > 0) {
+ return '';
+ }
+ } else {
+ $imageUrl = $this->getImageUrlFromElement($image);
+ if (!$this->isAllowedByImageUrl($imageUrl)) {
+ return '';
+ }
- $imageUrl = $this->getImageUrlFromElement($image);
- if (!$this->isAllowedByImageUrl($imageUrl)) {
- return '';
- }
-
- $images = $this->imageCollector->collect($imageUrl);
- if (!count($images) > 0) {
- return '';
+ $images = $this->imageCollector->collect($imageUrl);
+ if (!count($images) > 0) {
+ return '';
+ }
}
$imageHtml = $this->getImageHtmlFromImage($image, $html);
@@ -271,6 +291,7 @@ private function replaceInlineCssBackgroundImages(string $html): string
private function getImageUrlFromElement(DOMElement $image): string
{
$attributes = $this->getAllowedSrcAttributes();
+
$imageUrl = '';
foreach ($attributes as $attribute) {
$imageUrl = $image->getAttribute($attribute);
diff --git a/view/frontend/templates/picture.phtml b/view/frontend/templates/picture.phtml
index 709ab31..55cb853 100644
--- a/view/frontend/templates/picture.phtml
+++ b/view/frontend/templates/picture.phtml
@@ -1 +1,22 @@
-getWidth()) ? ' width="'.$block->getWidth().'"' : ''; $height = ($block->getHeight()) ? ' height="'.$block->getHeight().'"' : ''; $class = ($block->getClass()) ? ' class="'.$block->getClass().'"' : ''; $lazyLoading = ($block->getLazyLoading()) ? ' loading="lazy" ' : ''; $originalTag = trim($block->getOriginalTag()); $originalTag = preg_replace('/(\/?)>$/', $lazyLoading.'\1>', $originalTag); $originalImage = $block->getOriginalImage(); $originalImageType = $block->getOriginalImageType(); $srcAttribute = $block->getSrcAttribute() ?? 'src'; $srcSetAttribute = $srcAttribute.'set'; ?> getDebug()): ?> >getDebug()): ?> getImages() as $image): ?> ="= /* @noEscape */ $image->getUrl() ?>" = /* @noEscape */ $block->getSourceAttributesAsString() ?> > = /* @noEscape */ $originalTag ?>
\ No newline at end of file
+getWidth()) ? ' width="'.$block->getWidth().'"' : '';
+$height = ($block->getHeight()) ? ' height="'.$block->getHeight().'"' : '';
+$class = ($block->getClass()) ? ' class="'.$block->getClass().'"' : '';
+$lazyLoading = ($block->getLazyLoading()) ? ' loading="lazy" ' : '';
+$originalTag = trim($block->getOriginalTag());
+$originalTag = preg_replace('/(\/?)>$/', $lazyLoading.'\1>', $originalTag);
+$originalImage = $block->getOriginalImage();
+$originalImageType = $block->getOriginalImageType();
+$srcAttribute = $block->getSrcAttribute() ?? 'src';
+$srcSetAttribute = $srcAttribute.'set'; ?>
+
+getDebug()): ?>
+>
+ getDebug()): ?>
+ getImages() as $image): ?>
+ ="= /* @noEscape */ $image->getSrcSet() ?: $image->getUrl() ?>" = /* @noEscape */ $block->getSourceAttributesAsString() ?> >
+
+ = /* @noEscape */ $originalTag ?>
+