Skip to content

Commit 04c5df6

Browse files
Merge pull request #3 from basecom/develop
Add configuration for and handling of other image types
2 parents 51aa677 + 443ae38 commit 04c5df6

File tree

14 files changed

+417
-85
lines changed

14 files changed

+417
-85
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1515

1616
### Fixed
1717

18+
## [1.0.0] - 2025-03-28
19+
20+
### Added
21+
22+
* Support for resizing all image types
23+
* Separate configurations for `thumbnail`,`image`,`smallImage` and `swatchImage`
24+
* Configuration for resize mode, allowing for manual or automatic configuration of
25+
* Automatic: Read image ids from the theme's view.xml file
26+
* Manuel: Enter the image dimensions manually
27+
28+
Special thanks to [Kiel Pykettk](https://github.com/pykettk) for his [contribution](https://github.com/basecom/magento2-live-search-image-urls/pull/2)! 🧡
29+
1830
## [0.9.0] - 2025-03-24
1931

2032
- Release of this project 🎉
2133

2234
[0.9.0]: https://github.com/basecom/magento2-live-search-image-urls/releases/tag/v0.9.0
35+
[1.0.0]: https://github.com/basecom/magento2-live-search-image-urls/releases/tag/v1.0.0
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Basecom\LiveSearchImageUrls\Model\Config\Source;
4+
5+
use Magento\Framework\Data\OptionSourceInterface;
6+
7+
class SelectedImageTypes implements OptionSourceInterface
8+
{
9+
public const IMAGE_TYPE_NONE = 'none';
10+
public const IMAGE_TYPE_THUMBNAIL = 'thumbnail';
11+
public const IMAGE_TYPE_IMAGE = 'image';
12+
public const IMAGE_TYPE_SMALL_IMAGE = 'small_image';
13+
public const IMAGE_TYPE_SWATCH_IMAGE = 'swatch_image';
14+
15+
public function toOptionArray(): array
16+
{
17+
return [
18+
['value' => self::IMAGE_TYPE_NONE, 'label' =>
19+
__(ucwords(self::IMAGE_TYPE_NONE))],
20+
['value' => self::IMAGE_TYPE_THUMBNAIL, 'label' =>
21+
__(ucwords(self::IMAGE_TYPE_THUMBNAIL))],
22+
['value' => self::IMAGE_TYPE_IMAGE, 'label' =>
23+
__(ucwords(self::IMAGE_TYPE_IMAGE))],
24+
['value' => self::IMAGE_TYPE_SMALL_IMAGE, 'label' =>
25+
__(ucwords(str_replace('_', ' ', self::IMAGE_TYPE_SMALL_IMAGE)))],
26+
['value' => self::IMAGE_TYPE_SWATCH_IMAGE, 'label' =>
27+
__(ucwords(str_replace('_', ' ', self::IMAGE_TYPE_SWATCH_IMAGE)))],
28+
];
29+
}
30+
}

Model/Config/Source/ViewXmlImageTypes.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
class ViewXmlImageTypes implements OptionSourceInterface
1111
{
1212
public function __construct(
13-
private readonly ArrayManager $arrayManager,
14-
private readonly ConfigInterface $viewConfig
13+
private readonly ArrayManager $arrayManager,
14+
private readonly ConfigInterface $viewConfig,
15+
private readonly string $imageType = 'thumbnail'
1516
) {
1617
}
1718

@@ -22,11 +23,15 @@ public function toOptionArray(): array
2223
$imageConfig = $this->arrayManager->get('media/Magento_Catalog/images', $viewConfig) ?? [];
2324

2425
foreach ($imageConfig as $type => $config) {
26+
if (!isset($config['type']) || $config['type'] !== $this->imageType) {
27+
continue;
28+
}
29+
2530
$suffix = '';
2631

27-
if (array_key_exists('width', $config)) {
32+
if (isset($config['width'])) {
2833
$widthSuffix = 'W: ' . $config['width'] . 'px';
29-
$heightSuffix = array_key_exists('height', $config)
34+
$heightSuffix = isset($config['height'])
3035
? 'H: ' . $config['height'] . 'px'
3136
: 'H: auto';
3237

Plugin/SetCachedImageUrls.php

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace Basecom\LiveSearchImageUrls\Plugin;
55

6+
use Basecom\LiveSearchImageUrls\Model\Config\Source\SelectedImageTypes;
67
use Basecom\LiveSearchImageUrls\Model\Config\Source\SizeMode;
78
use Basecom\LiveSearchImageUrls\System\ModuleConfig;
89
use Magento\Catalog\Helper\Image as ImageHelper;
@@ -26,17 +27,15 @@ class SetCachedImageUrls
2627
* @param ProductFactory $productFactory
2728
* @param ArrayManager $arrayManager
2829
* @param ConfigInterface $viewConfig
29-
* @param int|null $fallbackHeight
30-
* @param int|null $fallbackWidth
30+
* @param array|null $fallbackDimensions
3131
*/
3232
public function __construct(
3333
private readonly ModuleConfig $moduleConfig,
3434
private readonly ImageHelper $imageHelper,
3535
private readonly ProductFactory $productFactory,
3636
private readonly ArrayManager $arrayManager,
3737
private readonly ConfigInterface $viewConfig,
38-
private readonly ?int $fallbackHeight = null,
39-
private readonly ?int $fallbackWidth = null,
38+
private readonly ?array $fallbackDimensions = null,
4039
) {
4140
}
4241

@@ -70,24 +69,38 @@ private function getProduct(): Product
7069
*/
7170
public function afterFormat(ImageFormatter $subject, array $result, array $row): array
7271
{
73-
$imageFilePath = $row['thumbnail'] ?? null;
72+
$resizeImageTypes = $this->moduleConfig->getResizeImageTypes();
7473

75-
if (!$imageFilePath) {
74+
if (in_array(SelectedImageTypes::IMAGE_TYPE_NONE, $resizeImageTypes, true)) {
7675
return $result;
7776
}
7877

79-
$result['thumbnail']['url'] = $this->getResizedImageUrl($imageFilePath);
78+
foreach ($resizeImageTypes as $imageType) {
79+
$imageTypeSnakeCase = $this->fromSnakeToCamelCase($imageType);
80+
$imageFilePath = $row[$imageTypeSnakeCase] ?? null;
81+
82+
if (!$imageFilePath) {
83+
return $result;
84+
}
85+
86+
$result[$imageTypeSnakeCase]['url'] = $this->getResizedImageUrl($imageType, $imageFilePath);
87+
}
8088

8189
return $result;
8290
}
8391

92+
private function fromSnakeToCamelCase(string $input): string
93+
{
94+
return lcfirst(str_replace('_', '', ucwords($input, '_')));
95+
}
96+
8497
/**
8598
* Retrieve resized image url for a given image file
8699
*
87100
* @param string $imageFile
88101
* @return string
89102
*/
90-
private function getResizedImageUrl(string $imageFile): string
103+
private function getResizedImageUrl(string $imageType, string $imageFile): string
91104
{
92105
$imageHelper = $this->imageHelper->init($this->getProduct(), 'product_page_image_small');
93106

@@ -99,23 +112,23 @@ private function getResizedImageUrl(string $imageFile): string
99112
return $imageHelper->getDefaultPlaceholderUrl('thumbnail');
100113
}
101114

102-
$imageDimensions = $this->getImageDimensions();
115+
$imageDimensions = $this->getImageDimensions($imageType);
103116

104117
return $imageHelper->setImageFile($imageFile)
105118
->resize($imageDimensions['width'], $imageDimensions['height'])
106119
->getUrl();
107120
}
108121

109-
private function getImageDimensions(): array
122+
private function getImageDimensions(string $imageType): array
110123
{
111124
if ($this->moduleConfig->getResizeMode() === SizeMode::MODE_MANUAL) {
112125
return [
113-
'height' => $this->moduleConfig->getResizeHeight(),
114-
'width' => $this->moduleConfig->getResizeWidth(),
126+
'height' => $this->moduleConfig->getResizeHeight($imageType),
127+
'width' => $this->moduleConfig->getResizeWidth($imageType),
115128
];
116129
}
117130

118-
if ($imageId = $this->moduleConfig->getImageId()) {
131+
if ($imageId = $this->moduleConfig->getImageId($imageType)) {
119132
$imageConfig = $this->arrayManager->get(
120133
sprintf('media/Magento_Catalog/images/%s', $imageId),
121134
$this->getFrontendViewConfig()
@@ -128,8 +141,8 @@ private function getImageDimensions(): array
128141
}
129142

130143
return [
131-
'height' => $this->fallbackHeight,
132-
'width' => $this->fallbackWidth,
144+
'height' => $this->fallbackDimensions[$imageType]['height'],
145+
'width' => $this->fallbackDimensions[$imageType]['width'],
133146
];
134147
}
135148

README.md

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,14 @@
1010

1111
---
1212

13-
When preparing the data for the catalog export to live search, die catalog data export module does not consider the resized, cached files.
13+
When preparing the data for the catalog export to live search, the catalog data export module does not consider the resized, cached files.
1414
Instead, the unchanged source file (selected in the admin area) is used. This has considerable performance implications, because the images are now a lot bigger than they need to be.
1515
Depending on the implementation, this can affect the entire catalog and product listing page, but will in any case affect the search popover.
1616

17-
This module adds a plugin to the `ImageFormatter::format()` method, which correctly resizes the thumbnails for the search popover.
17+
This module adds a plugin to the `ImageFormatter::format()` method, which correctly resizes the images that are synced to the live search catalog.
1818
This fixes the [issue](https://gitlab.hyva.io/hyva-enterprise/sensei/magento2-ee-magento-live-search/-/issues/9) opened in the Hyva-Enterprise repository
1919
(You may need to be given access to view the issue).
2020

21-
In the future, the other image types (`image` and `smallImage`) will be supported as well.
22-
2321
## Installation
2422

2523
1. Install the module via composer
@@ -37,11 +35,29 @@ In the future, the other image types (`image` and `smallImage`) will be supporte
3735

3836
## Configuration
3937

40-
There is no configuration available (yet). In the future, this module will be extended by a configuration to allow for resizing other relevant images as well, namely:
41-
* image
42-
* smallImage
38+
The module can be configured under `Stores > Configuration > Live Search > Storefront Features > Resize Images`.
39+
You can select all images types (`thumbnail`, `image`,`smallImage`,`swatchImage`) that you want to be considered for resizing.
40+
Selecting `none` (default value) will overrule any selections and no resizing will take effect.
41+
42+
![resize_images.png](docs/images/resize_images.png)
43+
44+
### Resize Mode
45+
46+
There are two available resize modes:
47+
48+
**Manual**:
49+
50+
Allows you to manually configure the width and height dimensions of each image.
51+
52+
![thumbnail_mode_manual.png](docs/images/thumbnail_mode_manual.png)
53+
54+
55+
**Automatic** (default):
56+
57+
Select an image id from the defined images in the `view.xml` file. The images are taken from the theme that is configured for the default store view.
58+
This approach is recommended, as you avoid duplication and unnecessary resizing of additional dimensions.
4359

44-
For now, it only supports resizing of the thumbnail image.
60+
![thumbnail_mode_automatic.png](docs/images/thumbnail_mode_automatic.png)
4561

4662
## Testing
4763

@@ -68,7 +84,7 @@ After the reindex has finished, it may take some time for Live Search to sync th
6884
you could add a `dump($result['thumbnail']['url']);` statement to the `afterFormat()` function before returning.
6985

7086
> [!NOTE]
71-
> Please make sure that the selected default image for the `thumbnail` is already correctly resized. Resizing this image programmatically may lead to incorrect results.
87+
> Please make sure that the selected placeholder image for the thumbnail and smaller images is already correctly resized. Resizing this image programmatically may lead to incorrect results.
7288
> You can change it under `Stores > Configuration > Catalog > Catalog > Product Image Placeholders > Thumbnail`.
7389

7490
## Contributing

System/ModuleConfig.php

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33

44
namespace Basecom\LiveSearchImageUrls\System;
55

6+
use Basecom\LiveSearchImageUrls\Model\Config\Source\SelectedImageTypes;
67
use Magento\Framework\App\Config\ScopeConfigInterface;
78
use Magento\Store\Model\ScopeInterface;
89

910
class ModuleConfig
1011
{
11-
private const XML_PATH_RESIZE_MODE = 'storefront_features/image_dimensions/size_mode';
12-
private const XML_PATH_RESIZE_IMAGE_ID = 'storefront_features/image_dimensions/image_id';
13-
private const XML_PATH_RESIZE_HEIGHT = 'storefront_features/image_dimensions/resize_height';
14-
private const XML_PATH_RESIZE_WIDTH = 'storefront_features/image_dimensions/resize_width';
12+
private const XML_PATH_RESIZE_IMAGE_TYPES = 'storefront_features/resize_images/image_types';
13+
private const XML_PATH_RESIZE_MODE = 'storefront_features/resize_images/resize_mode';
14+
private const XML_PATH_RESIZE_IMAGE_ID = 'storefront_features/resize_images/%s/image_id';
15+
private const XML_PATH_RESIZE_HEIGHT = 'storefront_features/resize_images/%s/resize_height';
16+
private const XML_PATH_RESIZE_WIDTH = 'storefront_features/resize_images/%s/resize_width';
1517

1618
public function __construct(
1719
private readonly ScopeConfigInterface $scopeConfig
@@ -23,20 +25,31 @@ public function getResizeMode($scopeId = null): ?string
2325
return $this->scopeConfig->getValue(self::XML_PATH_RESIZE_MODE, ScopeInterface::SCOPE_STORE, $scopeId);
2426
}
2527

26-
public function getImageId($scopeId = null): ?string
28+
public function getResizeImageTypes($scopeId = null): array
2729
{
28-
return $this->scopeConfig->getValue(self::XML_PATH_RESIZE_IMAGE_ID, ScopeInterface::SCOPE_STORE, $scopeId);
30+
$resizeImageTypes = $this->scopeConfig
31+
->getValue(self::XML_PATH_RESIZE_IMAGE_TYPES, ScopeInterface::SCOPE_STORE, $scopeId)
32+
?? SelectedImageTypes::IMAGE_TYPE_NONE;
33+
return explode(',', $resizeImageTypes);
2934
}
3035

31-
public function getResizeHeight($scopeId = null): ?int
36+
public function getImageId(string $imageType, $scopeId = null): ?string
3237
{
33-
return (int)$this->scopeConfig->getValue(self::XML_PATH_RESIZE_HEIGHT, ScopeInterface::SCOPE_STORE, $scopeId)
38+
$configPath = sprintf(self::XML_PATH_RESIZE_IMAGE_ID, $imageType);
39+
return $this->scopeConfig->getValue($configPath, ScopeInterface::SCOPE_STORE, $scopeId);
40+
}
41+
42+
public function getResizeHeight(string $imageType, $scopeId = null): ?int
43+
{
44+
$configPath = sprintf(self::XML_PATH_RESIZE_HEIGHT, $imageType);
45+
return (int)$this->scopeConfig->getValue($configPath, ScopeInterface::SCOPE_STORE, $scopeId)
3446
?? null;
3547
}
3648

37-
public function getResizeWidth($scopeId = null): ?int
49+
public function getResizeWidth(string $imageType, $scopeId = null): ?int
3850
{
39-
return (int)$this->scopeConfig->getValue(self::XML_PATH_RESIZE_WIDTH, ScopeInterface::SCOPE_STORE, $scopeId)
51+
$configPath = sprintf(self::XML_PATH_RESIZE_WIDTH, $imageType);
52+
return (int)$this->scopeConfig->getValue($configPath, ScopeInterface::SCOPE_STORE, $scopeId)
4053
?? null;
4154
}
4255
}

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "basecom/magento2-live-search-image-urls",
3-
"version": "0.9.0",
3+
"version": "1.0.0",
44
"description": "Magento2 module to reference the correctly resized image urls in Live Search",
55
"type": "magento2-module",
66
"license": [

docs/images/resize_images.png

49.8 KB
Loading
142 KB
Loading
44.9 KB
Loading

0 commit comments

Comments
 (0)