Skip to content

Commit 8cd5d77

Browse files
committed
Cloudinary category image - fix for non cloudinary images
1 parent 8b4bd1e commit 8cd5d77

1 file changed

Lines changed: 91 additions & 24 deletions

File tree

Plugin/Catalog/Block/Category/Image.php

Lines changed: 91 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,49 @@
22

33
namespace Cloudinary\Cloudinary\Plugin\Catalog\Block\Category;
44

5-
use Magento\Catalog\ViewModel\Category\Image as CategoryImageViewModel;
65
use Cloudinary\Asset\Media;
76
use Cloudinary\Cloudinary\Core\ConfigurationInterface;
87
use Cloudinary\Cloudinary\Core\ConfigurationBuilder;
98
use Cloudinary\Cloudinary\Core\Image\Transformation;
109
use Cloudinary\Configuration\Configuration;
11-
use Magento\Framework\View\Element\Block\ArgumentInterface;
1210
use Magento\Catalog\Model\Category;
1311
use Cloudinary\Cloudinary\Core\Image as CoreImage;
1412
use Cloudinary\Cloudinary\Model\ResourceModel\MediaLibraryMap\CollectionFactory as MediaLibraryMapCollectionFactory;
13+
use Magento\Catalog\ViewModel\Category\Image as CategoryImageViewModel;
1514

1615
class Image
1716
{
17+
/**
18+
* @var ConfigurationInterface
19+
*/
1820
protected $configuration;
21+
22+
/**
23+
* @var ConfigurationBuilder
24+
*/
1925
protected $configurationBuilder;
26+
27+
/**
28+
* @var Transformation
29+
*/
2030
protected $transformation;
31+
32+
/**
33+
* @var MediaLibraryMapCollectionFactory
34+
*/
2135
protected $mediaLibraryMapCollectionFactory;
2236

37+
/**
38+
* @var bool
39+
*/
2340
private $authorised = false;
2441

42+
/**
43+
* @param ConfigurationInterface $configuration
44+
* @param ConfigurationBuilder $configurationBuilder
45+
* @param Transformation $transformation
46+
* @param MediaLibraryMapCollectionFactory $mediaLibraryMapCollectionFactory
47+
*/
2548
public function __construct(
2649
ConfigurationInterface $configuration,
2750
ConfigurationBuilder $configurationBuilder,
@@ -34,6 +57,11 @@ public function __construct(
3457
$this->mediaLibraryMapCollectionFactory = $mediaLibraryMapCollectionFactory;
3558
}
3659

60+
/**
61+
* Authorize Cloudinary configuration
62+
*
63+
* @return void
64+
*/
3765
protected function authorise()
3866
{
3967
if (!$this->authorised && $this->configuration->isEnabled()) {
@@ -44,9 +72,19 @@ protected function authorise()
4472

4573
/**
4674
* Plugin after getUrl to return Cloudinary version
75+
*
76+
* For rendition images (.renditions/*) without local mapping, returns the local image URL.
77+
* For regular uploaded images, returns the Cloudinary URL.
78+
*
79+
* @param CategoryImageViewModel $subject
80+
* @param string $result
81+
* @param Category $category
82+
* @param string $attributeCode
83+
* @return string
84+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
4785
*/
4886
public function afterGetUrl(
49-
\Magento\Catalog\ViewModel\Category\Image $subject,
87+
CategoryImageViewModel $subject,
5088
string $result,
5189
Category $category,
5290
string $attributeCode = 'image'
@@ -59,40 +97,69 @@ public function afterGetUrl(
5997
}
6098

6199
try {
62-
$filename = preg_replace('/\.[^.]+$/', '', ltrim($imagePath, '/'));
63-
$publicId = null;
64-
65-
// Try to find mapping by searching cld_public_id with the filename pattern
66-
67-
$collection = $this->mediaLibraryMapCollectionFactory->create();
68-
$collection->addFieldToFilter('cld_public_id', ['like' => '%' . $filename]);
69-
70-
if ($collection->getSize() > 0) {
71-
$mapping = $collection->getFirstItem();
72-
// Use exact public_id from mapping (already without extension)
73-
$publicId = $mapping->getData('cld_public_id');
100+
$imageId = ltrim($imagePath, '/');
101+
$isRenditionImage = strpos($imageId, '.renditions/') !== false;
102+
103+
// Check if this is a rendition image (gallery selection or other rendition)
104+
// These images are stored locally and should not use Cloudinary unless there's a mapping
105+
if ($isRenditionImage && !$this->configuration->isEnabledLocalMapping()) {
106+
// Local mapping not enabled - return local image URL for rendition images
107+
return $result;
74108
}
75109

76-
// Fallback: construct public_id from imagePath (without extension)
77-
if (!$publicId) {
78-
if (preg_match('/cld_[a-zA-Z0-9]+_/', $filename)) {
79-
$filename = preg_replace('/cld_[a-zA-Z0-9]+_/', '', $filename);
80-
}
81-
$publicId = $filename;
82-
}
110+
// Try to find mapping if local mapping is enabled
111+
if ($this->configuration->isEnabledLocalMapping()) {
112+
$mappedPublicId = $this->getMappedPublicId($imageId);
113+
if ($mappedPublicId) {
114+
// If it's a full URL, return it directly
115+
if (preg_match('/https?:\/\//i', $mappedPublicId)) {
116+
return $mappedPublicId;
117+
}
118+
$imageId = $mappedPublicId;
119+
} elseif ($isRenditionImage) {
120+
// Rendition image without mapping - return local image URL
121+
return $result;
122+
}
123+
}
83124

84-
$asset = Media::fromParams($publicId, [
125+
// Generate Cloudinary URL using the imageId
126+
$imagePath = Media::fromParams($imageId, [
85127
'transformation' => $this->transformation->build(),
86128
'secure' => true,
87129
'sign_url' => $this->configuration->getUseSignedUrls(),
88130
'version' => 1
89131
]) . '?_i=AB';
90132

91-
$image = CoreImage::fromPath($asset, '');
133+
$image = CoreImage::fromPath($imagePath, '');
92134
return (string) $image;
93135

94136
} catch (\Exception $e) {
95137
return $result; // fallback to original if Cloudinary fails
96138
}
97139
}
140+
141+
/**
142+
* Get mapped public ID from database
143+
*
144+
* @param string $imageId
145+
* @return string|null
146+
*/
147+
private function getMappedPublicId($imageId)
148+
{
149+
preg_match('/(cld_[A-Za-z0-9]{13}_).+$/i', $imageId, $cldUniqid);
150+
if (!$cldUniqid || !isset($cldUniqid[1])) {
151+
return null;
152+
}
153+
154+
$mapped = $this->mediaLibraryMapCollectionFactory->create()
155+
->addFieldToFilter('cld_uniqid', $cldUniqid[1])
156+
->setPageSize(1)
157+
->getFirstItem();
158+
159+
if ($mapped && ($origPublicId = $mapped->getCldPublicId())) {
160+
return $origPublicId;
161+
}
162+
163+
return null;
164+
}
98165
}

0 commit comments

Comments
 (0)