Skip to content

Commit 8b4bd1e

Browse files
committed
Cloudinary - fix for category image not displaying
1 parent eea3328 commit 8b4bd1e

6 files changed

Lines changed: 94 additions & 13 deletions

File tree

Controller/Adminhtml/Ajax/System/Config/AutoUploadMapping.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
class AutoUploadMapping extends Action
2121
{
2222
const AUTO_UPLOAD_SETUP_FAIL_MESSAGE = 'Error. Unable to setup auto upload mapping.';
23+
const NON_AJAX_REQUEST = 'Rejected: Non-ajax request';
2324

2425
/**
2526
* @var JsonFactory

Core/CloudinaryImageManager.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,32 +56,38 @@ public function __construct(
5656
*/
5757
public function uploadAndSynchronise(Image $image, ?OutputInterface $output = null, $retryAttempt = 0)
5858
{
59+
$uploadResult = null;
5960
if (!$this->configuration->isEnabled() || !$this->configuration->hasEnvironmentVariable()) {
6061
return;
6162
}
6263

6364
try {
65+
6466
$this->report($output, sprintf(self::MESSAGE_UPLOADING_IMAGE, $image));
65-
$this->cloudinaryImageProvider->upload($image);
67+
$uploadResult = $this->cloudinaryImageProvider->upload($image);
6668
} catch (FileExists $e) {
6769
$this->report($output, sprintf(self::MESSAGE_UPLOADED_EXISTS, $image));
70+
$uploadResult['file_exist'] = preg_replace('/\.[^.]+$/', '', $image->getRelativePath());
71+
6872
} catch (\Exception $e) {
6973
if ($e->getMessage() === FileExists::DEFAULT_MESSAGE) {
7074
$this->report($output, sprintf(self::MESSAGE_UPLOADED_EXISTS, $image));
75+
$uploadResult['file_exist'] = preg_replace('/\.[^.]+$/', '', $image->getRelativePath());
7176
} else {
7277
if ($retryAttempt < self::MAXIMUM_RETRY_ATTEMPTS) {
7378
$retryAttempt++;
7479
$this->report($output, sprintf(self::MESSAGE_RETRY, $e->getMessage(), $retryAttempt));
7580
usleep(rand(10, 1000) * 1000);
7681
$this->uploadAndSynchronise($image, $output, $retryAttempt);
77-
return;
82+
return $uploadResult;
7883
}
7984

8085
throw $e;
8186
}
8287
}
8388

8489
$this->synchronisationRepository->saveAsSynchronized($image->getRelativePath());
90+
return $uploadResult;
8591
}
8692

8793
/**

Plugin/Catalog/Block/Category/Image.php

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,27 @@
1111
use Magento\Framework\View\Element\Block\ArgumentInterface;
1212
use Magento\Catalog\Model\Category;
1313
use Cloudinary\Cloudinary\Core\Image as CoreImage;
14+
use Cloudinary\Cloudinary\Model\ResourceModel\MediaLibraryMap\CollectionFactory as MediaLibraryMapCollectionFactory;
1415

1516
class Image
1617
{
1718
protected $configuration;
1819
protected $configurationBuilder;
1920
protected $transformation;
21+
protected $mediaLibraryMapCollectionFactory;
2022

2123
private $authorised = false;
2224

2325
public function __construct(
2426
ConfigurationInterface $configuration,
2527
ConfigurationBuilder $configurationBuilder,
26-
Transformation $transformation
28+
Transformation $transformation,
29+
MediaLibraryMapCollectionFactory $mediaLibraryMapCollectionFactory
2730
) {
2831
$this->configuration = $configuration;
2932
$this->configurationBuilder = $configurationBuilder;
3033
$this->transformation = $transformation;
34+
$this->mediaLibraryMapCollectionFactory = $mediaLibraryMapCollectionFactory;
3135
}
3236

3337
protected function authorise()
@@ -55,9 +59,27 @@ public function afterGetUrl(
5559
}
5660

5761
try {
62+
$filename = preg_replace('/\.[^.]+$/', '', ltrim($imagePath, '/'));
63+
$publicId = null;
5864

59-
$filename = pathinfo($imagePath, PATHINFO_FILENAME);
60-
$publicId = preg_replace('/^cld_[a-f0-9]+_/', '', $filename);
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');
74+
}
75+
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+
}
6183

6284
$asset = Media::fromParams($publicId, [
6385
'transformation' => $this->transformation->build(),

Plugin/FileUploader.php

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
use Cloudinary\Cloudinary\Core\CloudinaryImageManager;
66
use Cloudinary\Cloudinary\Core\ConfigurationInterface;
77
use Cloudinary\Cloudinary\Core\Image;
8+
use Cloudinary\Cloudinary\Model\MediaLibraryMapFactory;
89
use Magento\Framework\App\Filesystem\DirectoryList;
910
use Magento\Framework\File\Uploader;
11+
use Magento\Framework\Filesystem;
1012

1113
class FileUploader
1214
{
@@ -27,20 +29,36 @@ class FileUploader
2729
*/
2830
private $configuration;
2931

32+
/**
33+
* @var MediaLibraryMapFactory
34+
*/
35+
private $mediaLibraryMapFactory;
36+
37+
/**
38+
* @var Filesystem
39+
*/
40+
private $filesystem;
41+
3042
/**
3143
* @method __construct
3244
* @param CloudinaryImageManager $cloudinaryImageManager
3345
* @param DirectoryList $directoryList
3446
* @param ConfigurationInterface $configuration
47+
* @param MediaLibraryMapFactory $mediaLibraryMapFactory
48+
* @param Filesystem $filesystem
3549
*/
3650
public function __construct(
3751
CloudinaryImageManager $cloudinaryImageManager,
3852
DirectoryList $directoryList,
39-
ConfigurationInterface $configuration
53+
ConfigurationInterface $configuration,
54+
MediaLibraryMapFactory $mediaLibraryMapFactory,
55+
Filesystem $filesystem
4056
) {
4157
$this->cloudinaryImageManager = $cloudinaryImageManager;
4258
$this->directoryList = $directoryList;
4359
$this->configuration = $configuration;
60+
$this->mediaLibraryMapFactory = $mediaLibraryMapFactory;
61+
$this->filesystem = $filesystem;
4462
}
4563

4664
/**
@@ -56,10 +74,38 @@ public function afterSave(Uploader $uploader, $result)
5674

5775
$filepath = $this->absoluteFilePath($result);
5876

59-
if ($this->isAllowedImageExtension($filepath) && $this->isMediaFilePath($filepath) && !$this->isMediaTmpFilePath($filepath)) {
60-
$this->cloudinaryImageManager->uploadAndSynchronise(
61-
Image::fromPath($filepath, $this->mediaRelativePath($filepath))
62-
);
77+
78+
79+
if ($this->isAllowedImageExtension($filepath) && $this->isMediaFilePath($filepath)) {
80+
try {
81+
$relativePath = $this->mediaRelativePath($filepath);
82+
83+
// Normalize path: remove /tmp/ to match final location
84+
$normalizedPath = preg_replace('#/tmp/#', '/', $relativePath);
85+
86+
$image = Image::fromPath($filepath, $normalizedPath);
87+
$uploadResults = $this->cloudinaryImageManager->uploadAndSynchronise($image);
88+
89+
// fallback to existing files
90+
if (isset($uploadResults['file_exists']) && $uploadResults['file_exists']) {
91+
$normalizedPath = $uploadResults['file_exists'];
92+
}
93+
94+
// Only save mapping if upload succeeded and settings enabled
95+
$cldUniqid = $this->configuration->generateCLDuniqid();
96+
// Save public_id without extension (e.g., media/catalog/category/_4_2_3)
97+
$publicId = isset($uploadResults['public_id']) ? $uploadResults['public_id'] : preg_replace('/\.[^.]+$/', '', $normalizedPath);
98+
$this->mediaLibraryMapFactory->create()
99+
->setCldUniqid($cldUniqid)
100+
->setCldPublicId($publicId)
101+
->setFreeTransformation(null)
102+
->save();
103+
104+
} catch (\Cloudinary\Cloudinary\Core\Exception\FileExists $e) {
105+
// Image already exists in Cloudinary - skip mapping creation
106+
} catch (\Exception $e) {
107+
// Upload failed - skip mapping creation
108+
}
63109
}
64110

65111
return $result;
@@ -89,7 +135,13 @@ protected function isMediaFilePath($filepath)
89135
*/
90136
protected function isMediaTmpFilePath($filepath)
91137
{
92-
return strpos($filepath, sprintf('%s/tmp', $this->directoryList->getPath('media'))) === 0;
138+
// Check for standard tmp path
139+
$standardTmpCheck = strpos($filepath, sprintf('%s/tmp', $this->directoryList->getPath('media'))) === 0;
140+
141+
// Also check for catalog/tmp (category images go to catalog/tmp/category)
142+
$catalogTmpCheck = strpos($filepath, $this->directoryList->getPath('media') . '/catalog/tmp') === 0;
143+
144+
return $standardTmpCheck || $catalogTmpCheck;
93145
}
94146

95147
/**

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "cloudinary/cloudinary-magento2",
33
"description": "Cloudinary Magento 2 Integration.",
44
"type": "magento2-module",
5-
"version": "2.1.1",
5+
"version": "2.1.2",
66
"license": "MIT",
77
"require": {
88
"php": ">=7.3",

etc/module.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0"?>
22
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
3-
<module name="Cloudinary_Cloudinary" setup_version="2.1.1">
3+
<module name="Cloudinary_Cloudinary" setup_version="2.1.2">
44
<sequence>
55
<module name="Magento_ProductVideo"/>
66
<module name="Magento_PageBuilder"/>

0 commit comments

Comments
 (0)