Cloudinary_Cloudinary - Version 2.8.1

Version Notes

- Chain resizing after free transforms

Download this release

Release Info

Developer Cloudinary
Extension Cloudinary_Cloudinary
Version 2.8.1
Comparing to
See all releases


Code changes from version 2.7.0 to 2.8.1

Files changed (27) hide show
  1. app/code/community/Cloudinary/Cloudinary/Block/Adminhtml/Catalog/Product/Edit/Gallery.php +111 -0
  2. app/code/community/Cloudinary/Cloudinary/Block/Adminhtml/Catalog/Product/Edit/Tab.php +35 -0
  3. app/code/community/Cloudinary/Cloudinary/Block/Adminhtml/Manage.php +10 -0
  4. app/code/community/Cloudinary/Cloudinary/Helper/Image.php +34 -2
  5. app/code/community/Cloudinary/Cloudinary/Helper/Reset.php +1 -0
  6. app/code/community/Cloudinary/Cloudinary/Model/AdminProductObserver.php +106 -0
  7. app/code/community/Cloudinary/Cloudinary/Model/Cache.php +38 -0
  8. app/code/community/Cloudinary/Cloudinary/Model/Catalog/Product/Media/Config.php +29 -11
  9. app/code/community/Cloudinary/Cloudinary/Model/Configuration.php +1 -1
  10. app/code/community/Cloudinary/Cloudinary/Model/Resource/Transformation.php +14 -0
  11. app/code/community/Cloudinary/Cloudinary/Model/Resource/Transformation/Collection.php +9 -0
  12. app/code/community/Cloudinary/Cloudinary/Model/SynchronizationChecker.php +15 -18
  13. app/code/community/Cloudinary/Cloudinary/Model/System/Config/Free.php +33 -0
  14. app/code/community/Cloudinary/Cloudinary/Model/System/Config/Source/Dropdown/Gravity.php +1 -1
  15. app/code/community/Cloudinary/Cloudinary/Model/Transformation.php +94 -0
  16. app/code/community/Cloudinary/Cloudinary/controllers/Adminhtml/CloudinaryController.php +4 -2
  17. app/code/community/Cloudinary/Cloudinary/controllers/Adminhtml/CloudinaryajaxController.php +22 -12
  18. app/code/community/Cloudinary/Cloudinary/controllers/Adminhtml/CloudinaryproductController.php +10 -0
  19. app/code/community/Cloudinary/Cloudinary/etc/config.xml +13 -3
  20. app/code/community/Cloudinary/Cloudinary/etc/system.xml +2 -2
  21. app/code/community/Cloudinary/Cloudinary/sql/cloudinary_setup/upgrade-2.6.0-2.7.0.php +8 -0
  22. app/code/community/Cloudinary/Cloudinary/sql/cloudinary_setup/upgrade-2.7.0-2.8.0.php +29 -0
  23. app/design/adminhtml/default/default/layout/cloudinary/cloudinary.xml +18 -0
  24. app/design/adminhtml/default/default/template/cloudinary/catalog/product/gallery.phtml +222 -0
  25. app/design/adminhtml/default/default/template/cloudinary/manage.phtml +15 -0
  26. lib/CloudinaryExtension/Image/Transformation.php +2 -2
  27. package.xml +5 -7
app/code/community/Cloudinary/Cloudinary/Block/Adminhtml/Catalog/Product/Edit/Gallery.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Cloudinary_Cloudinary_Block_Adminhtml_Catalog_Product_Edit_Gallery extends Mage_Core_Block_Template
4
+ {
5
+ public function __construct()
6
+ {
7
+ $this->_blockGroup = 'cloudinary_cloudinary';
8
+ $this->_controller = 'adminhtml_cloudinaryproduct';
9
+ $this->_headerText = Mage::helper('cloudinary_cloudinary')->__('Cloudinary ');
10
+ parent::__construct();
11
+ }
12
+
13
+ /**
14
+ * @return bool
15
+ */
16
+ public function isCloudinaryEnabled()
17
+ {
18
+ return Mage::getModel('cloudinary_cloudinary/configuration')->isEnabled();
19
+ }
20
+
21
+ /**
22
+ * @return string
23
+ */
24
+ public function getCloudinaryConfigurationLink()
25
+ {
26
+ return Mage::helper("adminhtml")->getUrl("adminhtml/system_config/edit/section/cloudinary");
27
+ }
28
+
29
+ /**
30
+ * @return array
31
+ */
32
+ public function getImages()
33
+ {
34
+ return $this->injectFreeTransformations(
35
+ $this->convertImagesToObjects(
36
+ $this->getMediaGallery($this->getProduct())
37
+ )
38
+ );
39
+ }
40
+
41
+ /**
42
+ * @return string
43
+ */
44
+ public function ajaxSampleSecretKey()
45
+ {
46
+ return Mage::getModel('adminhtml/url')->getSecretKey('cloudinaryajax', 'sample');
47
+ }
48
+
49
+ /**
50
+ * @return Mage_Catalog_Model_Product
51
+ */
52
+ public function getProduct()
53
+ {
54
+ return Mage::registry('product') ?: $this->loadProductFromRequest();
55
+ }
56
+
57
+ /**
58
+ * @return Mage_Catalog_Model_Product
59
+ */
60
+ private function loadProductFromRequest()
61
+ {
62
+ return Mage::getModel('catalog/product')->load(Mage::app()->getRequest()->getParam('id'));
63
+ }
64
+
65
+ /**
66
+ * @param Mage_Catalog_Model_Product $product
67
+ * @return array
68
+ */
69
+ private function getMediaGallery(Mage_Catalog_Model_Product $product)
70
+ {
71
+ $gallery = $product->getMediaGallery();
72
+
73
+ if (!$gallery || !is_array($gallery) || !array_key_exists('images', $gallery)) {
74
+ return [];
75
+ }
76
+
77
+ return $gallery['images'];
78
+ }
79
+
80
+ /**
81
+ * @param array $images
82
+ * @return [Varien_Object]
83
+ */
84
+ private function convertImagesToObjects(array $images)
85
+ {
86
+ return array_map(
87
+ function(array $image) {
88
+ $object = new Varien_Object();
89
+ return $object->setData($image);
90
+ },
91
+ $images
92
+ );
93
+ }
94
+
95
+ /**
96
+ * @param [Varien_Object] $images
97
+ * @return [Varien_Object]
98
+ */
99
+ private function injectFreeTransformations(array $images)
100
+ {
101
+ return array_map(
102
+ function(Varien_Object $image) {
103
+ $model = Mage::getModel('cloudinary_cloudinary/transformation');
104
+ $model->load($image->getFile());
105
+ $image->setFreeTransformation($model->getFreeTransformation());
106
+ return $image;
107
+ },
108
+ $images
109
+ );
110
+ }
111
+ }
app/code/community/Cloudinary/Cloudinary/Block/Adminhtml/Catalog/Product/Edit/Tab.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Cloudinary_Cloudinary_Block_Adminhtml_Catalog_Product_Edit_Tab extends Mage_Adminhtml_Block_Widget
4
+ implements Mage_Adminhtml_Block_Widget_Tab_Interface
5
+ {
6
+ public function canShowTab()
7
+ {
8
+ return true;
9
+ }
10
+
11
+ public function getTabLabel()
12
+ {
13
+ return $this->__('Cloudinary');
14
+ }
15
+
16
+ public function getTabTitle()
17
+ {
18
+ return $this->__('Cloudinary');
19
+ }
20
+
21
+ public function isHidden()
22
+ {
23
+ return false;
24
+ }
25
+
26
+ public function getTabUrl()
27
+ {
28
+ return $this->getUrl('*/cloudinaryproduct/gallery', array('_current' => true));
29
+ }
30
+
31
+ public function getTabClass()
32
+ {
33
+ return 'ajax';
34
+ }
35
+ }
app/code/community/Cloudinary/Cloudinary/Block/Adminhtml/Manage.php CHANGED
@@ -62,6 +62,11 @@ class Cloudinary_Cloudinary_Block_Adminhtml_Manage extends Mage_Adminhtml_Block_
62
  return $this->_cloudinaryConfig->isEnabled();
63
  }
64
 
 
 
 
 
 
65
  public function allImagesSynced()
66
  {
67
  try {
@@ -114,6 +119,11 @@ class Cloudinary_Cloudinary_Block_Adminhtml_Manage extends Mage_Adminhtml_Block_
114
  return $button->toHtml();
115
  }
116
 
 
 
 
 
 
117
  public function getErrors()
118
  {
119
  $coll = Mage::getModel('cloudinary_cloudinary/migrationError')->getCollection();
62
  return $this->_cloudinaryConfig->isEnabled();
63
  }
64
 
65
+ public function isAutoUploadMappingEnabled()
66
+ {
67
+ return $this->_cloudinaryConfig->hasAutoUploadMapping();
68
+ }
69
+
70
  public function allImagesSynced()
71
  {
72
  try {
119
  return $button->toHtml();
120
  }
121
 
122
+ public function getCloudinaryConfigurationLink()
123
+ {
124
+ return Mage::helper("adminhtml")->getUrl("adminhtml/system_config/edit/section/cloudinary");
125
+ }
126
+
127
  public function getErrors()
128
  {
129
  $coll = Mage::getModel('cloudinary_cloudinary/migrationError')->getCollection();
app/code/community/Cloudinary/Cloudinary/Helper/Image.php CHANGED
@@ -2,7 +2,6 @@
2
 
3
  use CloudinaryExtension\CloudinaryImageProvider;
4
  use CloudinaryExtension\Configuration;
5
- use CloudinaryExtension\Image;
6
  use CloudinaryExtension\Image\Transformation;
7
  use CloudinaryExtension\Image\Transformation\Dimensions;
8
  use CloudinaryExtension\Image\Transformation\Crop;
@@ -41,6 +40,11 @@ class Cloudinary_Cloudinary_Helper_Image extends Mage_Catalog_Helper_Image
41
  */
42
  private $_urlGenerator;
43
 
 
 
 
 
 
44
  public function __construct()
45
  {
46
  $this->_configuration = Mage::getModel('cloudinary_cloudinary/configuration');
@@ -51,8 +55,15 @@ class Cloudinary_Cloudinary_Helper_Image extends Mage_Catalog_Helper_Image
51
  $this->_imageProvider = CloudinaryImageProvider::fromConfiguration($this->_configuration);
52
  $this->_dimensions = Dimensions::null();
53
  $this->_urlGenerator = new UrlGenerator($this->_configuration, $this->_imageProvider);
 
54
  }
55
 
 
 
 
 
 
 
56
  public function init(Mage_Catalog_Model_Product $product, $attributeName, $imageFile = null)
57
  {
58
  if ($this->_configuration->isEnabled()) {
@@ -63,6 +74,11 @@ class Cloudinary_Cloudinary_Helper_Image extends Mage_Catalog_Helper_Image
63
  return parent::init($product, $attributeName, $imageFile);
64
  }
65
 
 
 
 
 
 
66
  public function resize($width, $height = null)
67
  {
68
  $this->_dimensions = Dimensions::fromWidthAndHeight($width, $height);
@@ -70,6 +86,10 @@ class Cloudinary_Cloudinary_Helper_Image extends Mage_Catalog_Helper_Image
70
  return parent::resize($width, $height);
71
  }
72
 
 
 
 
 
73
  public function getImageUrlForCategory(Mage_Catalog_Model_Category $category)
74
  {
75
  $imagePath = Mage::getBaseDir('media') . DS . 'catalog' . DS . 'category' . DS . $category->getImage();
@@ -79,6 +99,9 @@ class Cloudinary_Cloudinary_Helper_Image extends Mage_Catalog_Helper_Image
79
  return $this->_urlGenerator->generateFor($image);
80
  }
81
 
 
 
 
82
  public function __toString()
83
  {
84
  $image = $this->_imageFactory->build(
@@ -86,7 +109,13 @@ class Cloudinary_Cloudinary_Helper_Image extends Mage_Catalog_Helper_Image
86
  function() { return parent::__toString();}
87
  );
88
 
89
- return $this->_urlGenerator->generateFor($image, $this->createTransformation());
 
 
 
 
 
 
90
  }
91
 
92
  /**
@@ -97,6 +126,9 @@ class Cloudinary_Cloudinary_Helper_Image extends Mage_Catalog_Helper_Image
97
  return $this->getImageFile() ?: $this->getProduct()->getData($this->_attributeName);
98
  }
99
 
 
 
 
100
  private function createTransformation()
101
  {
102
  if ($this->_getModel()->getKeepFrameState()) {
2
 
3
  use CloudinaryExtension\CloudinaryImageProvider;
4
  use CloudinaryExtension\Configuration;
 
5
  use CloudinaryExtension\Image\Transformation;
6
  use CloudinaryExtension\Image\Transformation\Dimensions;
7
  use CloudinaryExtension\Image\Transformation\Crop;
40
  */
41
  private $_urlGenerator;
42
 
43
+ /**
44
+ * @var Cloudinary_Cloudinary_Model_Transformation
45
+ */
46
+ private $_transformation;
47
+
48
  public function __construct()
49
  {
50
  $this->_configuration = Mage::getModel('cloudinary_cloudinary/configuration');
55
  $this->_imageProvider = CloudinaryImageProvider::fromConfiguration($this->_configuration);
56
  $this->_dimensions = Dimensions::null();
57
  $this->_urlGenerator = new UrlGenerator($this->_configuration, $this->_imageProvider);
58
+ $this->_transformation = Mage::getModel('cloudinary_cloudinary/transformation');
59
  }
60
 
61
+ /**
62
+ * @param Mage_Catalog_Model_Product $product
63
+ * @param $attributeName
64
+ * @param string|null $imageFile
65
+ * @return $this
66
+ */
67
  public function init(Mage_Catalog_Model_Product $product, $attributeName, $imageFile = null)
68
  {
69
  if ($this->_configuration->isEnabled()) {
74
  return parent::init($product, $attributeName, $imageFile);
75
  }
76
 
77
+ /**
78
+ * @param $width
79
+ * @param null $height
80
+ * @return $this
81
+ */
82
  public function resize($width, $height = null)
83
  {
84
  $this->_dimensions = Dimensions::fromWidthAndHeight($width, $height);
86
  return parent::resize($width, $height);
87
  }
88
 
89
+ /**
90
+ * @param Mage_Catalog_Model_Category $category
91
+ * @return string
92
+ */
93
  public function getImageUrlForCategory(Mage_Catalog_Model_Category $category)
94
  {
95
  $imagePath = Mage::getBaseDir('media') . DS . 'catalog' . DS . 'category' . DS . $category->getImage();
99
  return $this->_urlGenerator->generateFor($image);
100
  }
101
 
102
+ /**
103
+ * @return string
104
+ */
105
  public function __toString()
106
  {
107
  $image = $this->_imageFactory->build(
109
  function() { return parent::__toString();}
110
  );
111
 
112
+ return $this->_urlGenerator->generateFor(
113
+ $image,
114
+ $this->_transformation->addFreeformTransformationForImage(
115
+ $this->createTransformation(),
116
+ $this->_getRequestedImageFile()
117
+ )
118
+ );
119
  }
120
 
121
  /**
126
  return $this->getImageFile() ?: $this->getProduct()->getData($this->_attributeName);
127
  }
128
 
129
+ /**
130
+ * @return Transformation
131
+ */
132
  private function createTransformation()
133
  {
134
  if ($this->_getModel()->getKeepFrameState()) {
app/code/community/Cloudinary/Cloudinary/Helper/Reset.php CHANGED
@@ -8,6 +8,7 @@ class Cloudinary_Cloudinary_Helper_Reset extends Mage_Core_Helper_Abstract
8
  {
9
  $this->truncateCollection('cloudinary_cloudinary/synchronisation');
10
  $this->truncateCollection('cloudinary_cloudinary/migrationError');
 
11
  $this->removeConfigurationData();
12
  $this->removeMigration();
13
  $this->clearConfigCache();
8
  {
9
  $this->truncateCollection('cloudinary_cloudinary/synchronisation');
10
  $this->truncateCollection('cloudinary_cloudinary/migrationError');
11
+ $this->truncateCollection('cloudinary_cloudinary/transformation');
12
  $this->removeConfigurationData();
13
  $this->removeMigration();
14
  $this->clearConfigCache();
app/code/community/Cloudinary/Cloudinary/Model/AdminProductObserver.php ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use Varien_Event_Observer as EventObserver;
4
+ use Mage_Catalog_Model_Product as Product;
5
+
6
+ class Cloudinary_Cloudinary_Model_AdminProductObserver extends Mage_Core_Model_Abstract
7
+ {
8
+ const CLOUDINARY_FREE_FORM_FIELD = 'cloudinary_free';
9
+ const CLOUDINARY_FREE_UPDATED_FIELD = 'cloudinary_free_updated';
10
+
11
+ /**
12
+ * @param Varien_Event_Observer $event
13
+ * @throws Exception
14
+ */
15
+ public function beforeProductSave(EventObserver $event)
16
+ {
17
+ $product = $event->getProduct();
18
+ $post = Mage::app()->getRequest()->getPost();
19
+
20
+ if ($product && $post && array_key_exists(self::CLOUDINARY_FREE_FORM_FIELD, $post)) {
21
+ $this->validateFreeTransformValues(
22
+ $this->filterUpdatedImages(
23
+ $post[self::CLOUDINARY_FREE_FORM_FIELD],
24
+ $post[self::CLOUDINARY_FREE_UPDATED_FIELD]
25
+ )
26
+ );
27
+ $this->storeFreeTransformFields($post[self::CLOUDINARY_FREE_FORM_FIELD], $product);
28
+ }
29
+ }
30
+
31
+ /**
32
+ * @param array $imageData
33
+ * @param array $imageUpdated
34
+ * @return array
35
+ */
36
+ private function filterUpdatedImages(array $imageData, array $imageUpdated)
37
+ {
38
+ return array_filter(
39
+ $imageData,
40
+ function($id) use ($imageUpdated) {
41
+ return $imageUpdated[$id];
42
+ },
43
+ ARRAY_FILTER_USE_KEY
44
+ );
45
+ }
46
+
47
+ /**
48
+ * @param array $imageData
49
+ * @throws Exception
50
+ */
51
+ private function validateFreeTransformValues(array $imageData)
52
+ {
53
+ if (!count($imageData)) {
54
+ return;
55
+ }
56
+
57
+ $model = Mage::getModel('cloudinary_cloudinary/system_config_free');
58
+ if (!$model->hasAccountConfigured()) {
59
+ throw new \Exception('Cloudinary credentials required');
60
+ }
61
+
62
+ foreach ($imageData as $transform) {
63
+ $model->validateImageUrl($model->sampleImageUrl($model->defaultTransform($transform)));
64
+ }
65
+ }
66
+
67
+ /**
68
+ * @param array $imageData
69
+ */
70
+ private function storeFreeTransformFields(array $imageData, Mage_Catalog_Model_Product $product)
71
+ {
72
+ $mediaImages = $this->getMediaGalleryImages($product);
73
+
74
+ foreach ($imageData as $id => $freeTransform) {
75
+ Mage::getModel('cloudinary_cloudinary/transformation')
76
+ ->setImageName($this->getImageNameForId($id, $mediaImages))
77
+ ->setFreeTransformation($freeTransform)
78
+ ->save();
79
+ }
80
+ }
81
+
82
+ /**
83
+ * @param string $id
84
+ * @param array $images
85
+ * @return string
86
+ */
87
+ private function getImageNameForId($id, $images)
88
+ {
89
+ foreach ($images as $image) {
90
+ if ($image['value_id'] == $id) {
91
+ return $image['file'];
92
+ }
93
+ }
94
+
95
+ return '';
96
+ }
97
+
98
+ /**
99
+ * @param Mage_Catalog_Model_Product $product
100
+ * @return array
101
+ */
102
+ private function getMediaGalleryImages(Mage_Catalog_Model_Product $product)
103
+ {
104
+ return json_decode($product->getMediaGallery()['images'], true);
105
+ }
106
+ }
app/code/community/Cloudinary/Cloudinary/Model/Cache.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Cloudinary_Cloudinary_Model_Cache extends Mage_Core_Model_Abstract
4
+ {
5
+ const CACHE_NAME = 'cloudinary';
6
+ const CACHE_TAG = 'CLOUDINARY';
7
+
8
+ private $mageCache;
9
+
10
+ public function _construct()
11
+ {
12
+ $this->mageCache = Mage::app()->getCacheInstance();
13
+ }
14
+
15
+ public function isEnabled()
16
+ {
17
+ return $this->mageCache->canUse(self::CACHE_NAME);
18
+ }
19
+
20
+ public function save($key, $value)
21
+ {
22
+ $this->mageCache->save($value, $key, [self::CACHE_TAG]);
23
+ }
24
+
25
+ public function load($key, callable $uncachedCall = null)
26
+ {
27
+ $value = $this->isEnabled()
28
+ ? $this->mageCache->load($key)
29
+ : false;
30
+
31
+ if ($value === false && !is_null($uncachedCall)) {
32
+ $value = $uncachedCall();
33
+ $this->save($key, $value);
34
+ }
35
+
36
+ return $value;
37
+ }
38
+ }
app/code/community/Cloudinary/Cloudinary/Model/Catalog/Product/Media/Config.php CHANGED
@@ -1,39 +1,57 @@
1
  <?php
2
 
3
- use CloudinaryExtension\Cloud;
4
  use CloudinaryExtension\CloudinaryImageProvider;
5
- use CloudinaryExtension\Image;
6
  use CloudinaryExtension\Image\ImageFactory;
7
  use CloudinaryExtension\UrlGenerator;
8
 
9
  class Cloudinary_Cloudinary_Model_Catalog_Product_Media_Config extends Mage_Catalog_Model_Product_Media_Config
10
  {
11
- private $_configuration;
12
- private $_imageProvider;
 
 
 
 
 
 
13
  private $_urlGenerator;
14
 
15
  public function __construct()
16
  {
17
- $this->_configuration = Mage::getModel('cloudinary_cloudinary/configuration');
 
18
  $this->_imageFactory = new ImageFactory(
19
- $this->_configuration,
20
  Mage::getModel('cloudinary_cloudinary/synchronizationChecker')
21
  );
22
- $this->_imageProvider = CloudinaryImageProvider::fromConfiguration($this->_configuration);
23
- $this->_urlGenerator = new UrlGenerator($this->_configuration, $this->_imageProvider);
24
 
 
 
 
 
25
  }
26
 
 
 
 
 
27
  public function getMediaUrl($file)
28
  {
29
- $image = $this->_imageFactory->build($file, function() use($file) { return parent::getMediaUrl($file);});
30
 
31
- return $this->_urlGenerator->generateFor($image);
 
 
 
32
  }
33
 
 
 
 
 
34
  public function getTmpMediaUrl($file)
35
  {
36
- $image = $this->_imageFactory->build($file, function() use($file) { return parent::getTmpMediaUrl($file);});
37
 
38
  return $this->_urlGenerator->generateFor($image);
39
  }
1
  <?php
2
 
 
3
  use CloudinaryExtension\CloudinaryImageProvider;
 
4
  use CloudinaryExtension\Image\ImageFactory;
5
  use CloudinaryExtension\UrlGenerator;
6
 
7
  class Cloudinary_Cloudinary_Model_Catalog_Product_Media_Config extends Mage_Catalog_Model_Product_Media_Config
8
  {
9
+ /**
10
+ * @var ImageFactory
11
+ */
12
+ private $_imageFactory;
13
+
14
+ /**
15
+ * @var UrlGenerator
16
+ */
17
  private $_urlGenerator;
18
 
19
  public function __construct()
20
  {
21
+ $configuration = Mage::getModel('cloudinary_cloudinary/configuration');
22
+
23
  $this->_imageFactory = new ImageFactory(
24
+ $configuration,
25
  Mage::getModel('cloudinary_cloudinary/synchronizationChecker')
26
  );
 
 
27
 
28
+ $this->_urlGenerator = new UrlGenerator(
29
+ $configuration,
30
+ CloudinaryImageProvider::fromConfiguration($configuration)
31
+ );
32
  }
33
 
34
+ /**
35
+ * @param string $file relative image filepath
36
+ * @return string
37
+ */
38
  public function getMediaUrl($file)
39
  {
40
+ $image = $this->_imageFactory->build($file, function() use($file) { return parent::getMediaUrl($file); });
41
 
42
+ return $this->_urlGenerator->generateFor(
43
+ $image,
44
+ Mage::getModel('cloudinary_cloudinary/transformation')->transformationForImage($file)
45
+ );
46
  }
47
 
48
+ /**
49
+ * @param string $file relative image filepath
50
+ * @return string
51
+ */
52
  public function getTmpMediaUrl($file)
53
  {
54
+ $image = $this->_imageFactory->build($file, function() use($file) { return parent::getTmpMediaUrl($file); });
55
 
56
  return $this->_urlGenerator->generateFor($image);
57
  }
app/code/community/Cloudinary/Cloudinary/Model/Configuration.php CHANGED
@@ -164,7 +164,7 @@ class Cloudinary_Cloudinary_Model_Configuration implements ConfigurationInterfac
164
  /**
165
  * @return bool
166
  */
167
- private function hasAutoUploadMapping()
168
  {
169
  return Mage::getModel('cloudinary_cloudinary/autoUploadMapping_configuration')->isActive();
170
  }
164
  /**
165
  * @return bool
166
  */
167
+ public function hasAutoUploadMapping()
168
  {
169
  return Mage::getModel('cloudinary_cloudinary/autoUploadMapping_configuration')->isActive();
170
  }
app/code/community/Cloudinary/Cloudinary/Model/Resource/Transformation.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Cloudinary_Cloudinary_Model_Resource_Transformation extends Mage_Core_Model_Resource_Db_Abstract
4
+ {
5
+ /**
6
+ * @var bool
7
+ */
8
+ protected $_isPkAutoIncrement = false;
9
+
10
+ protected function _construct()
11
+ {
12
+ $this->_init('cloudinary_cloudinary/transformation', 'image_name');
13
+ }
14
+ }
app/code/community/Cloudinary/Cloudinary/Model/Resource/Transformation/Collection.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Cloudinary_Cloudinary_Model_Resource_Transformation_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
4
+ {
5
+ protected function _construct()
6
+ {
7
+ $this->_init('cloudinary_cloudinary/transformation');
8
+ }
9
+ }
app/code/community/Cloudinary/Cloudinary/Model/SynchronizationChecker.php CHANGED
@@ -4,9 +4,6 @@ use CloudinaryExtension\Image\SynchronizationChecker as SynchronizationCheckerIn
4
 
5
  class Cloudinary_Cloudinary_Model_SynchronizationChecker implements SynchronizationCheckerInterface
6
  {
7
- const CACHE_NAME = 'cloudinary';
8
- const CACHE_TAG = 'CLOUDINARY';
9
-
10
  /**
11
  * @param string $imageName
12
  * @return bool
@@ -21,9 +18,12 @@ class Cloudinary_Cloudinary_Model_SynchronizationChecker implements Synchronizat
21
  return true;
22
  }
23
 
24
- $cache = Mage::app()->getCacheInstance();
 
 
 
25
 
26
- if ($cache->canUse(self::CACHE_NAME)) {
27
  return $this->cachedSynchronizationCheck($cache, $imageName);
28
  }
29
 
@@ -55,26 +55,23 @@ class Cloudinary_Cloudinary_Model_SynchronizationChecker implements Synchronizat
55
  * @param string $imageName
56
  * @return string
57
  */
58
- private function cacheKey($imageName)
59
  {
60
- return sprintf('cloudinary_%s', md5($imageName));
61
  }
62
 
63
  /**
64
- * @param Mage_Core_Model_Cache $cache
65
  * @param string $imageName
66
  * @return bool
67
  */
68
- private function cachedSynchronizationCheck(Mage_Core_Model_Cache $cache, $imageName)
69
  {
70
- $key = $this->cacheKey($imageName);
71
- $value = $cache->load($key);
72
-
73
- if ($value === false) {
74
- $value = $this->synchronizationCheck($imageName) ? '1' : '0';
75
- $cache->save($value, $key, [self::CACHE_TAG]);
76
- }
77
-
78
- return $value === '1' ? true : false;
79
  }
80
  }
4
 
5
  class Cloudinary_Cloudinary_Model_SynchronizationChecker implements SynchronizationCheckerInterface
6
  {
 
 
 
7
  /**
8
  * @param string $imageName
9
  * @return bool
18
  return true;
19
  }
20
 
21
+ /**
22
+ * @var Cloudinary_Cloudinary_Model_Cache $cache
23
+ */
24
+ $cache = Mage::getSingleton('cloudinary_cloudinary/cache');
25
 
26
+ if ($cache->isEnabled()) {
27
  return $this->cachedSynchronizationCheck($cache, $imageName);
28
  }
29
 
55
  * @param string $imageName
56
  * @return string
57
  */
58
+ private function getSynchronizationCacheKeyFromImageName($imageName)
59
  {
60
+ return sprintf('cloudinary_sync_%s', md5($imageName));
61
  }
62
 
63
  /**
64
+ * @param Cloudinary_Cloudinary_Model_Cache $cache
65
  * @param string $imageName
66
  * @return bool
67
  */
68
+ private function cachedSynchronizationCheck(Cloudinary_Cloudinary_Model_Cache $cache, $imageName)
69
  {
70
+ return $cache->load(
71
+ $this->getSynchronizationCacheKeyFromImageName($imageName),
72
+ function () use ($imageName) {
73
+ return $this->synchronizationCheck($imageName) ? '1' : '0';
74
+ }
75
+ ) === '1' ? true : false;
 
 
 
76
  }
77
  }
app/code/community/Cloudinary/Cloudinary/Model/System/Config/Free.php CHANGED
@@ -59,6 +59,17 @@ class Cloudinary_Cloudinary_Model_System_Config_Free extends Mage_Core_Model_Con
59
  }
60
  }
61
 
 
 
 
 
 
 
 
 
 
 
 
62
  /**
63
  * @param Zend_Http_Response $response
64
  * @return string
@@ -102,4 +113,26 @@ class Cloudinary_Cloudinary_Model_System_Config_Free extends Mage_Core_Model_Con
102
  $transformation
103
  );
104
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  }
59
  }
60
  }
61
 
62
+ /**
63
+ * @param string $freeTransforma
64
+ * @return Transformation
65
+ */
66
+ public function defaultTransform($freeTransform)
67
+ {
68
+ return Mage::getModel('cloudinary_cloudinary/configuration')
69
+ ->getDefaultTransformation()
70
+ ->withFreeform(Freeform::fromString($freeTransform));
71
+ }
72
+
73
  /**
74
  * @param Zend_Http_Response $response
75
  * @return string
113
  $transformation
114
  );
115
  }
116
+
117
+ /**
118
+ * @param String $filename
119
+ * @param Transformation $transformation
120
+ * @return string
121
+ */
122
+ public function namedImageUrl($filename, Transformation $transformation)
123
+ {
124
+ if (empty($filename)) {
125
+ throw new RuntimeException('Error: missing image identifier');
126
+ }
127
+
128
+ $imageProvider = CloudinaryImageProvider::fromConfiguration($this->configuration);
129
+
130
+ return (string)$imageProvider->retrieveTransformed(
131
+ Image::fromPath(
132
+ $filename,
133
+ $this->configuration->isFolderedMigration() ? $this->configuration->getMigratedPath($filename) : ''
134
+ ),
135
+ $transformation
136
+ );
137
+ }
138
  }
app/code/community/Cloudinary/Cloudinary/Model/System/Config/Source/Dropdown/Gravity.php CHANGED
@@ -7,7 +7,7 @@ class Cloudinary_Cloudinary_Model_System_Config_Source_Dropdown_Gravity
7
  return array(
8
  array(
9
  'value' => '',
10
- 'label' => 'Default',
11
  ),
12
  array(
13
  'value' => 'face',
7
  return array(
8
  array(
9
  'value' => '',
10
+ 'label' => 'Magento\'s Default',
11
  ),
12
  array(
13
  'value' => 'face',
app/code/community/Cloudinary/Cloudinary/Model/Transformation.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use CloudinaryExtension\Image\Transformation;
4
+ use CloudinaryExtension\Image\Transformation\Freeform;
5
+
6
+ class Cloudinary_Cloudinary_Model_Transformation extends Mage_Core_Model_Abstract
7
+ {
8
+ const TRANSFORM_CACHE_WARM_KEY = 'cloudinary_transform_warm';
9
+
10
+ /**
11
+ * @var Cloudinary_Cloudinary_Model_Configuration
12
+ */
13
+ private $configuration;
14
+
15
+ /**
16
+ * @var Cloudinary_Cloudinary_Model_Cache
17
+ */
18
+ private $cache;
19
+
20
+ protected function _construct()
21
+ {
22
+ $this->configuration = Mage::getModel('cloudinary_cloudinary/configuration');
23
+ $this->cache = Mage::getSingleton('cloudinary_cloudinary/cache');
24
+ $this->_init('cloudinary_cloudinary/transformation');
25
+ }
26
+
27
+ /**
28
+ * @param string $imageFile
29
+ * @return Transformation
30
+ */
31
+ public function transformationForImage($imageFile)
32
+ {
33
+ return $this->addFreeformTransformationForImage(
34
+ $this->configuration->getDefaultTransformation(),
35
+ $imageFile
36
+ );
37
+ }
38
+
39
+ /**
40
+ * @param Transformation $transformation
41
+ * @param string $imageFile
42
+ * @return Transformation
43
+ */
44
+ public function addFreeformTransformationForImage(Transformation $transformation, $imageFile)
45
+ {
46
+ $transformationString = $this->cache->load(
47
+ $this->getTransformCacheKeyFromImageFile($imageFile),
48
+ function () use ($imageFile) {
49
+ $this->warmTransformationCache();
50
+
51
+ $this->load($imageFile);
52
+ if (($this->getImageName() === $imageFile) && $this->hasFreeTransformation()) {
53
+ return $this->getFreeTransformation();
54
+ }
55
+ return '';
56
+ }
57
+ );
58
+
59
+ if ($transformationString != false) {
60
+ $transformation->withFreeform(Freeform::fromString($transformationString));
61
+ }
62
+
63
+ return $transformation;
64
+ }
65
+
66
+ /**
67
+ * Loads the whole transformation collection into cache to alleviate page load problems
68
+ */
69
+ protected function warmTransformationCache()
70
+ {
71
+ if ($this->cache->isEnabled() && !$this->cache->load(self::TRANSFORM_CACHE_WARM_KEY)) {
72
+ foreach ($this->getCollection() as $transformation) {
73
+ $this->cache->save(
74
+ $this->getTransformCacheKeyFromImageFile($transformation->getImageName()),
75
+ $transformation->getFreeTransformation()
76
+ );
77
+ }
78
+ $this->cache->save(self::TRANSFORM_CACHE_WARM_KEY, '1');
79
+ }
80
+ }
81
+
82
+ private function getTransformCacheKeyFromImageFile($imageFile)
83
+ {
84
+ return sprintf('cloudinary_transform_%s', md5($imageFile));
85
+ }
86
+
87
+ /**
88
+ * @return bool
89
+ */
90
+ private function hasFreeTransformation()
91
+ {
92
+ return !empty($this->getFreeTransformation());
93
+ }
94
+ }
app/code/community/Cloudinary/Cloudinary/controllers/Adminhtml/CloudinaryController.php CHANGED
@@ -153,9 +153,11 @@ class Cloudinary_Cloudinary_Adminhtml_CloudinaryController extends Mage_Adminhtm
153
 
154
  private function _displayValidationFailureMessage()
155
  {
156
- $link = '<a href="/admin/system_config/edit/section/cloudinary/">here</a>';
157
  $this->_getSession()->addError(
158
- "Please enter your Cloudinary Credentials $link to Activate Cloudinary"
 
 
 
159
  );
160
  }
161
  }
153
 
154
  private function _displayValidationFailureMessage()
155
  {
 
156
  $this->_getSession()->addError(
157
+ sprintf(
158
+ 'Please enter your Cloudinary Credentials <a href="%s">here</a> to Activate Cloudinary',
159
+ Mage::helper("adminhtml")->getUrl("adminhtml/system_config/edit/section/cloudinary")
160
+ )
161
  );
162
  }
163
  }
app/code/community/Cloudinary/Cloudinary/controllers/Adminhtml/CloudinaryajaxController.php CHANGED
@@ -14,7 +14,7 @@ class Cloudinary_Cloudinary_Adminhtml_CloudinaryajaxController extends Mage_Admi
14
 
15
  $freeTransform = $this->getRequest()->getParam('free');
16
  $freeModel = Mage::getModel('cloudinary_cloudinary/system_config_free');
17
- $url = $freeModel->sampleImageUrl($this->defaultTransform($freeTransform));
18
  $this->validate($freeModel, $url);
19
  $this->jsonResponse(
20
  200,
@@ -25,6 +25,27 @@ class Cloudinary_Cloudinary_Adminhtml_CloudinaryajaxController extends Mage_Admi
25
  }
26
  }
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  /**
29
  * @param int $code
30
  * @param array $payload
@@ -38,17 +59,6 @@ class Cloudinary_Cloudinary_Adminhtml_CloudinaryajaxController extends Mage_Admi
38
  ->setBody(Mage::helper('core')->jsonEncode($payload));
39
  }
40
 
41
- /**
42
- * @param string $freeTransforma
43
- * @return Transformation
44
- */
45
- private function defaultTransform($freeTransform)
46
- {
47
- return Mage::getModel('cloudinary_cloudinary/configuration')
48
- ->getDefaultTransformation()
49
- ->withFreeform(Freeform::fromString($freeTransform));
50
- }
51
-
52
  /**
53
  * @param Cloudinary_Cloudinary_Model_System_Config_Free $model
54
  * @param string $url
14
 
15
  $freeTransform = $this->getRequest()->getParam('free');
16
  $freeModel = Mage::getModel('cloudinary_cloudinary/system_config_free');
17
+ $url = $freeModel->sampleImageUrl($freeModel->defaultTransform($freeTransform));
18
  $this->validate($freeModel, $url);
19
  $this->jsonResponse(
20
  200,
25
  }
26
  }
27
 
28
+ public function imageAction()
29
+ {
30
+ try {
31
+ $freeModel = Mage::getModel('cloudinary_cloudinary/system_config_free');
32
+
33
+ $url = $freeModel->namedImageUrl(
34
+ $this->getRequest()->getParam('image'),
35
+ $freeModel->defaultTransform($this->getRequest()->getParam('free'))
36
+ );
37
+
38
+ $this->validate($freeModel, $url);
39
+
40
+ $this->jsonResponse(
41
+ 200,
42
+ ['url' => $url]
43
+ );
44
+ } catch (\Exception $e) {
45
+ $this->jsonResponse(401, ['error' => $e->getMessage()]);
46
+ }
47
+ }
48
+
49
  /**
50
  * @param int $code
51
  * @param array $payload
59
  ->setBody(Mage::helper('core')->jsonEncode($payload));
60
  }
61
 
 
 
 
 
 
 
 
 
 
 
 
62
  /**
63
  * @param Cloudinary_Cloudinary_Model_System_Config_Free $model
64
  * @param string $url
app/code/community/Cloudinary/Cloudinary/controllers/Adminhtml/CloudinaryproductController.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Cloudinary_Cloudinary_Adminhtml_CloudinaryproductController extends Mage_Adminhtml_Controller_Action
4
+ {
5
+ public function galleryAction()
6
+ {
7
+ $this->loadLayout();
8
+ $this->renderLayout();
9
+ }
10
+ }
app/code/community/Cloudinary/Cloudinary/etc/config.xml CHANGED
@@ -2,7 +2,7 @@
2
  <config>
3
  <modules>
4
  <Cloudinary_Cloudinary>
5
- <version>2.7.0</version>
6
  </Cloudinary_Cloudinary>
7
  </modules>
8
  <global>
@@ -47,6 +47,9 @@
47
  <migrationError>
48
  <table>cloudinary_migration_error</table>
49
  </migrationError>
 
 
 
50
  </entities>
51
  </cloudinary_resource>
52
  </models>
@@ -76,7 +79,6 @@
76
  </catalog>
77
  <cloudinary_cloudinary>
78
  <class>Cloudinary_Cloudinary_Helper</class>
79
-
80
  </cloudinary_cloudinary>
81
  </helpers>
82
  <events>
@@ -119,7 +121,7 @@
119
  <types>
120
  <cloudinary translate="label,description" module="cloudinary">
121
  <label>Cloudinary</label>
122
- <description>Cache of all images migrated to Cloudinary. Not required when using auto upload mapping.</description>
123
  <tags>CLOUDINARY</tags>
124
  </cloudinary>
125
  </types>
@@ -143,6 +145,14 @@
143
  </cloudinary_config_changed>
144
  </observers>
145
  </admin_system_config_changed_section_cloudinary>
 
 
 
 
 
 
 
 
146
  </events>
147
  </adminhtml>
148
  <admin>
2
  <config>
3
  <modules>
4
  <Cloudinary_Cloudinary>
5
+ <version>2.8.1</version>
6
  </Cloudinary_Cloudinary>
7
  </modules>
8
  <global>
47
  <migrationError>
48
  <table>cloudinary_migration_error</table>
49
  </migrationError>
50
+ <transformation>
51
+ <table>cloudinary_transformation</table>
52
+ </transformation>
53
  </entities>
54
  </cloudinary_resource>
55
  </models>
79
  </catalog>
80
  <cloudinary_cloudinary>
81
  <class>Cloudinary_Cloudinary_Helper</class>
 
82
  </cloudinary_cloudinary>
83
  </helpers>
84
  <events>
121
  <types>
122
  <cloudinary translate="label,description" module="cloudinary">
123
  <label>Cloudinary</label>
124
+ <description>Cache of all product image transformations and all images migrated to Cloudinary.</description>
125
  <tags>CLOUDINARY</tags>
126
  </cloudinary>
127
  </types>
145
  </cloudinary_config_changed>
146
  </observers>
147
  </admin_system_config_changed_section_cloudinary>
148
+ <catalog_product_save_before>
149
+ <observers>
150
+ <product_before_save>
151
+ <class>cloudinary_cloudinary/adminProductObserver</class>
152
+ <method>beforeProductSave</method>
153
+ </product_before_save>
154
+ </observers>
155
+ </catalog_product_save_before>
156
  </events>
157
  </adminhtml>
158
  <admin>
app/code/community/Cloudinary/Cloudinary/etc/system.xml CHANGED
@@ -26,8 +26,8 @@
26
  <show_in_store>1</show_in_store>
27
  <fields>
28
  <cloudinary_environment_variable translate="label comment">
29
- <label>Cloudinary Account Credentials (CLOUDINARY_URL)</label>
30
- <comment>Set the credentials of your Cloudinary account. Copy the credentials string from the dashboard of Cloudinary's Management Console. It is available as the Environment variable of CLOUDINARY_URL.</comment>
31
  <frontend_type>password</frontend_type>
32
  <backend_model>adminhtml/system_config_backend_encrypted</backend_model>
33
  <sort_order>1</sort_order>
26
  <show_in_store>1</show_in_store>
27
  <fields>
28
  <cloudinary_environment_variable translate="label comment">
29
+ <label>Cloudinary Account Credentials</label>
30
+ <comment>Set the credentials of your Cloudinary account. Copy the "Environment variable" string from the dashboard of Cloudinary's Management Console.</comment>
31
  <frontend_type>password</frontend_type>
32
  <backend_model>adminhtml/system_config_backend_encrypted</backend_model>
33
  <sort_order>1</sort_order>
app/code/community/Cloudinary/Cloudinary/sql/cloudinary_setup/upgrade-2.6.0-2.7.0.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* @var $installer Mage_Core_Model_Resource_Setup */
4
+ $installer = $this;
5
+
6
+ $installer->startSetup();
7
+
8
+ $installer->endSetup();
app/code/community/Cloudinary/Cloudinary/sql/cloudinary_setup/upgrade-2.7.0-2.8.0.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* @var $installer Mage_Core_Model_Resource_Setup */
4
+ $installer = $this;
5
+ $installer->startSetup();
6
+
7
+ $table = $installer->getConnection()
8
+ ->newTable($installer->getTable('cloudinary_cloudinary/transformation'))
9
+ ->addColumn(
10
+ 'image_name',
11
+ Varien_Db_Ddl_Table::TYPE_VARCHAR,
12
+ 255,
13
+ [
14
+ 'nullable' => false,
15
+ 'primary' => true
16
+ ],
17
+ 'Relative image path'
18
+ )
19
+ ->addColumn(
20
+ 'free_transformation',
21
+ Varien_Db_Ddl_Table::TYPE_VARCHAR,
22
+ 255,
23
+ [],
24
+ 'Free transformation'
25
+ );
26
+
27
+ $installer->getConnection()->createTable($table);
28
+
29
+ $installer->endSetup();
app/design/adminhtml/default/default/layout/cloudinary/cloudinary.xml CHANGED
@@ -14,6 +14,7 @@
14
  </action>
15
  </reference>
16
  </adminhtml_cloudinary_index>
 
17
  <adminhtml_cloudinarylog_index>
18
  <reference name="content">
19
  <block type="cloudinary_cloudinary/adminhtml_log" name="cloudinary_log" template="cloudinary/log.phtml"></block>
@@ -28,6 +29,7 @@
28
  </action>
29
  </reference>
30
  </adminhtml_cloudinarylog_index>
 
31
  <adminhtml_cloudinaryreset_index>
32
  <update handle="editor"/>
33
  <reference name="content">
@@ -43,4 +45,20 @@
43
  </action>
44
  </reference>
45
  </adminhtml_cloudinaryreset_index>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  </layout>
14
  </action>
15
  </reference>
16
  </adminhtml_cloudinary_index>
17
+
18
  <adminhtml_cloudinarylog_index>
19
  <reference name="content">
20
  <block type="cloudinary_cloudinary/adminhtml_log" name="cloudinary_log" template="cloudinary/log.phtml"></block>
29
  </action>
30
  </reference>
31
  </adminhtml_cloudinarylog_index>
32
+
33
  <adminhtml_cloudinaryreset_index>
34
  <update handle="editor"/>
35
  <reference name="content">
45
  </action>
46
  </reference>
47
  </adminhtml_cloudinaryreset_index>
48
+
49
+ <adminhtml_catalog_product_edit>
50
+ <reference name="product_tabs">
51
+ <action method="addTab">
52
+ <name>Cloudinary</name>
53
+ <block>cloudinary_cloudinary/adminhtml_catalog_product_edit_tab</block>
54
+ </action>
55
+ </reference>
56
+ </adminhtml_catalog_product_edit>
57
+
58
+ <adminhtml_cloudinaryproduct_gallery>
59
+ <block type="core/text_list" name="root" output="toHtml">
60
+ <block type="cloudinary_cloudinary/adminhtml_catalog_product_edit_gallery" name="cloudinary_product_gallery" template="cloudinary/catalog/product/gallery.phtml"></block>
61
+ </block>
62
+ </adminhtml_cloudinaryproduct_gallery>
63
+
64
  </layout>
app/design/adminhtml/default/default/template/cloudinary/catalog/product/gallery.phtml ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php $images = $this->getImages(); ?>
2
+ <div class="entry-edit custom-options product-custom-options">
3
+ <div class="entry-edit-head">
4
+ <h4>Cloudinary product specific image transformations</h4>
5
+ </div>
6
+
7
+ <div class="box">
8
+
9
+ <div style="width: 60%;">
10
+
11
+ <?php if (count($images) && $this->isCloudinaryEnabled()): ?>
12
+
13
+ <div class="grid">
14
+ <table cellspacing="0" class="data border" id="media_gallery_content_grid" style="margin-top: 10px;">
15
+ <col width="250" />
16
+ <col width="200" />
17
+ <col />
18
+ <col width="100" />
19
+ <thead>
20
+ <tr class="headings">
21
+ <th><?php echo Mage::helper('catalog')->__('Image') ?></th>
22
+ <th><?php echo Mage::helper('catalog')->__('Label') ?></th>
23
+ <th><?php echo Mage::helper('cloudinary_cloudinary')->__('Cloudinary free transform') ?></th>
24
+ <th><?php echo Mage::helper('cloudinary_cloudinary')->__('Action') ?></th>
25
+ </tr>
26
+ </thead>
27
+ <tbody id="media_gallery_content_list">
28
+ <?php foreach($this->getImages() as $image): ?>
29
+ <tr>
30
+ <td class="cell-image" id="cloudinary_preview_container_<?php echo $image->getValueId(); ?>">
31
+ </td>
32
+ <td class="cell-label"><?php echo $image->getLabel(); ?></td>
33
+ <td>
34
+ <input type="text"
35
+ id="cloudinary_input_<?php echo $image->getValueId(); ?>"
36
+ name="cloudinary_free[<?php echo $image->getValueId(); ?>]"
37
+ value="<?php echo $image->getFreeTransformation(); ?>"
38
+ style="width: 80%;" />
39
+ <input type="hidden"
40
+ id="cloudinary_input_updated_<?php echo $image->getValueId(); ?>"
41
+ name="cloudinary_free_updated[<?php echo $image->getValueId(); ?>]"
42
+ value="" />
43
+ </td>
44
+ <td>
45
+ <button id="cloudinary_preview_button_<?php echo $image->getValueId(); ?>"
46
+ class="cloudinary_preview_button"
47
+ type="button"
48
+ data-file="<?php echo $image->getFile(); ?>"
49
+ data-id="<?php echo $image->getValueId(); ?>">
50
+ Preview
51
+ </button>
52
+ </td>
53
+ </tr>
54
+ <?php endforeach; ?>
55
+ </tbody>
56
+ </table>
57
+ </div>
58
+
59
+ <?php else: ?>
60
+
61
+ <ul class="messages">
62
+ <li class="notice-msg" style="background-image: none !important; margin: 10px 0;">
63
+ <?php if ($this->isCloudinaryEnabled()): ?>
64
+ <p>No product images are available</p>
65
+ <?php else: ?>
66
+ <p>
67
+ The Cloudinary module has not been configured. To use this feature please visit the
68
+ <a href="<?php echo $this->getCloudinaryConfigurationLink(); ?>">
69
+ Cloudinary Configuration page
70
+ </a>
71
+ and add an environment variable, then enable auto upload mapping or perform a
72
+ manual migration.
73
+ </p>
74
+ <?php endif; ?>
75
+ </li>
76
+ </ul>
77
+
78
+ <?php endif; ?>
79
+
80
+ <p>
81
+ Product image transformations will be added to the the site-wide default image transformation options
82
+ chosen from dropdowns on the Cloudinary config page. Product image transformations will override any
83
+ free form transformation options that have been specified in the 'Global custom transform' field
84
+ of the Cloudinary config page.
85
+ </p>
86
+ <p>
87
+ For information about the full range of transforms available see the
88
+ <a href="http://cloudinary.com/documentation/image_transformation_reference" target="_blank">
89
+ Cloudinary documentation
90
+ </a>.
91
+ </p>
92
+ <p>
93
+ You may need to clear or rebuild the Magento block, full page and Cloudinary caches to see the changes in the front end.
94
+ </p>
95
+
96
+ </div>
97
+
98
+ </div>
99
+ </div>
100
+
101
+ <script language="javascript">
102
+
103
+ window.cloudinary = {
104
+
105
+ currentTransform: {},
106
+
107
+ secret: '<?php echo $this->ajaxSampleSecretKey(); ?>',
108
+
109
+ getTransformText: function(id) {
110
+ return $('cloudinary_input_' + id).value
111
+ },
112
+
113
+ getAjaxImageUrl: function() {
114
+ return '/admin/cloudinaryajax/image/key/' + this.secret;
115
+ },
116
+
117
+ getImageId: function(id) {
118
+ return 'cloudinary_preview_' + id;
119
+ },
120
+
121
+ getImageContainerId: function(id) {
122
+ return 'cloudinary_preview_container_' + id;
123
+ },
124
+
125
+ getPreviewButtonId: function(id) {
126
+ return 'cloudinary_preview_button_' + id;
127
+ },
128
+
129
+ getInputUpdatedId: function(id) {
130
+ return 'cloudinary_input_updated_' + id;
131
+ },
132
+
133
+ setInputUpdated: function(id) {
134
+ $(this.getInputUpdatedId(id)).value = '1';
135
+ },
136
+
137
+ getImageFile: function(id) {
138
+ return $(this.getPreviewButtonId(id)).getAttribute('data-file');
139
+ },
140
+
141
+ getImageHtml: function(id, src) {
142
+ var id = this.getImageId(id),
143
+ style = 'width: auto; height: auto; max-width: 250px; max-height: 250px; min-height: 50px;';
144
+ return '<img id="' + id + '" src="' + src + '" style="' + style + '" />';
145
+ },
146
+
147
+ getErrorHtml: function(message) {
148
+ return '<ul class="messages"><li class="error-msg">' + message + '</li></ul>';
149
+ },
150
+
151
+ updatePreviewImage: function(id, url) {
152
+ var $image = $(this.getImageId(id));
153
+
154
+ if (!$image) {
155
+ $(this.getImageContainerId(id)).update(this.getImageHtml(id, url));
156
+ } else {
157
+ $image.writeAttribute('src', url);
158
+ }
159
+ },
160
+
161
+ updatePreview: function(id) {
162
+ var self = this;
163
+
164
+ if (!self.isPreviewActive(id)) {
165
+ return;
166
+ }
167
+
168
+ self.currentTransform[id] = self.getTransformText(id);
169
+ self.setPreviewActiveState(id, false);
170
+
171
+ new Ajax.Request(this.getAjaxImageUrl(), {
172
+ method: 'post',
173
+ parameters: { free: self.currentTransform[id], image: self.getImageFile(id) },
174
+ onSuccess: function(response) {
175
+ self.updatePreviewImage(id, response.responseJSON.url);
176
+ },
177
+ onFailure: function(response) {
178
+ $(self.getImageContainerId(id)).update(self.getErrorHtml(response.responseJSON.error));
179
+ }
180
+ });
181
+ },
182
+
183
+ setPreviewActiveState: function(id, state) {
184
+ if (state && (this.currentTransform[id] !== this.getTransformText(id))) {
185
+ this.setInputUpdated(id);
186
+ $(this.getPreviewButtonId(id)).removeClassName('disabled');
187
+ } else {
188
+ $(this.getPreviewButtonId(id)).addClassName('disabled');
189
+ }
190
+ },
191
+
192
+ isPreviewActive: function(id) {
193
+ return !$(this.getPreviewButtonId(id)).hasClassName('disabled');
194
+ },
195
+
196
+ addPreviewButtonListener: function(button) {
197
+ var self = this;
198
+
199
+ button.on('click', function() {
200
+ self.updatePreview(button.getAttribute('data-id'));
201
+ });
202
+ },
203
+
204
+ addTextChangeListener: function(id) {
205
+ var self = this,
206
+ input = $('cloudinary_input_' + id);
207
+
208
+ input.on('change', function() { self.setPreviewActiveState(id, true); });
209
+ input.on('keydown', function() { self.setPreviewActiveState(id, true); });
210
+ input.on('paste', function() { self.setPreviewActiveState(id, true); });
211
+ input.on('input', function() { self.setPreviewActiveState(id, true); });
212
+ }
213
+
214
+ };
215
+
216
+ $$('.cloudinary_preview_button').each(function(button) {
217
+ window.cloudinary.updatePreview(button.getAttribute('data-id'));
218
+ window.cloudinary.addPreviewButtonListener(button);
219
+ window.cloudinary.addTextChangeListener(button.getAttribute('data-id'));
220
+ });
221
+
222
+ </script>
app/design/adminhtml/default/default/template/cloudinary/manage.phtml CHANGED
@@ -47,6 +47,21 @@
47
  </tbody></table>
48
  </div>
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  <p>
51
  <?php if ($this->allImagesSynced()): ?>
52
  <div id="messages"><ul class="messages"><li class="notice-msg"><ul><li><span>All images have been successfully migrated to Cloudinary</span></li></ul></li></ul></div>
47
  </tbody></table>
48
  </div>
49
 
50
+ <p>
51
+ Manual migration is only required if auto upload mapping cannot be used. New images will be automatically
52
+ uploaded to Cloudinary when they are added to products or CMS pages.
53
+ </p>
54
+ <p>
55
+ <strong>
56
+ <?php if ($this->isAutoUploadMappingEnabled()): ?>
57
+ You have auto upload mapping enabled, and do not need to perform a manual migration.
58
+ <?php else: ?>
59
+ You can enable auto upload mapping in the
60
+ <a href="<?php echo $this->getCloudinaryConfigurationLink(); ?>">Cloudinary Configuration</a> section.
61
+ <?php endif; ?>
62
+ </strong>
63
+ </p>
64
+
65
  <p>
66
  <?php if ($this->allImagesSynced()): ?>
67
  <div id="messages"><ul class="messages"><li class="notice-msg"><ul><li><span>All images have been successfully migrated to Cloudinary</span></li></ul></li></ul></div>
lib/CloudinaryExtension/Image/Transformation.php CHANGED
@@ -85,6 +85,7 @@ class Transformation
85
  public function build()
86
  {
87
  return [
 
88
  [
89
  'fetch_format' => (string)$this->fetchFormat,
90
  'quality' => (string)$this->quality,
@@ -94,8 +95,7 @@ class Transformation
94
  'height' => $this->dimensions ? $this->dimensions->getHeight() : null,
95
  'dpr' => (string)$this->dpr,
96
  'flags' => $this->flags
97
- ],
98
- ['raw_transformation' => (string)$this->freeform]
99
  ];
100
  }
101
  }
85
  public function build()
86
  {
87
  return [
88
+ ['raw_transformation' => (string)$this->freeform],
89
  [
90
  'fetch_format' => (string)$this->fetchFormat,
91
  'quality' => (string)$this->quality,
95
  'height' => $this->dimensions ? $this->dimensions->getHeight() : null,
96
  'dpr' => (string)$this->dpr,
97
  'flags' => $this->flags
98
+ ]
 
99
  ];
100
  }
101
  }
package.xml CHANGED
@@ -1,21 +1,19 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Cloudinary_Cloudinary</name>
4
- <version>2.7.0</version>
5
  <stability>stable</stability>
6
  <license>MIT License (MITL)</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Cloudinary - Image Management In The Cloud</summary>
10
  <description>Cloudinary supercharges your images! Upload images to the cloud, deliver optimized via a fast CDN, perform smart resizing and apply effects.</description>
11
- <notes> Release 2.7.0 notes:&#xD;
12
- - Support free transform chained transformations&#xD;
13
- - Set format and quality defaults to auto&#xD;
14
  </notes>
15
  <authors><author><name>Cloudinary</name><user>cloudinary</user><email>accounts+magento@cloudinary.com</email></author></authors>
16
- <date>2017-06-19</date>
17
- <time>09:49:48</time>
18
- <contents><target name="magecommunity"><dir name="Cloudinary"><dir name="Cloudinary"><dir name="Block"><dir name="Adminhtml"><dir name="Log"><file name="Grid.php" hash="1f8c277b31e21a8d28bcb57716a9a1f7"/></dir><file name="Log.php" hash="d76ab8c1f2ab39137a2726437c6e487a"/><dir name="Manage"><file name="Grid.php" hash="b6a05f6ba08c5ba0d08846a7b0a06776"/></dir><file name="Manage.php" hash="c17b5839709263d544b7e27dac52da45"/><dir name="Page"><file name="Menu.php" hash="891d6a4c075ba03c9a20658076c86ad0"/></dir><dir name="Reset"><dir name="Edit"><file name="Form.php" hash="059109b8230f9404921fb53660fdb228"/></dir><file name="Edit.php" hash="6944d440bcedcef8d8d118ecb2e61019"/></dir><dir name="System"><dir name="Config"><dir name="Form"><file name="Free.php" hash="33a3aff8e241d6ca142c6dfb59c1a90b"/></dir><file name="Signup.php" hash="ed6accbe7a4ce16bb0679eaf0c2dbb22"/></dir></dir></dir></dir><dir name="Helper"><file name="Autoloader.php" hash="393b3e2fc25e63ca28157152d2542b18"/><file name="Config.php" hash="737331dc824063845b8b908c0d18f04c"/><file name="Console.php" hash="7c909e3226c51c05d6da1f6ff9cbbfc9"/><file name="Cron.php" hash="805557370a2006b15444b7a62bbbc65a"/><file name="Data.php" hash="42c9d44f1bbe530e30cf5379846dea65"/><file name="Image.php" hash="af1c1d734793d6b08feaa7e1abd591d0"/><file name="Reset.php" hash="a7baf65e9478dc8202971c22fa383b57"/></dir><dir name="Model"><dir name="AutoUploadMapping"><file name="Configuration.php" hash="a9c2e1176ec36cea6f5183b24793dc2d"/></dir><dir name="Catalog"><dir name="Product"><file name="Image.php" hash="b5d14bcb836158890152c9fed191f8bc"/><dir name="Media"><file name="Config.php" hash="c2dbac447d4a22c920c19b0d4eb2672e"/></dir><file name="Media.php" hash="05726616a07d7d08933e9654e6107283"/></dir></dir><dir name="Cms"><dir name="Adminhtml"><dir name="Template"><file name="Filter.php" hash="792893f6b4e884a8e42847d457a6068c"/></dir></dir><file name="Synchronisation.php" hash="8d830a18f169a0ff5f7d865e3afcb710"/><dir name="Template"><file name="Filter.php" hash="c3fe64f98128043de13e92156a26ab02"/></dir><file name="Uploader.php" hash="69d6855309eb35d78c532e4789d6d526"/><dir name="Wysiwyg"><dir name="Images"><file name="Storage.php" hash="0d23e557d6db06308886d9307fe92665"/></dir></dir></dir><file name="CollectionCounter.php" hash="e69953aee5d966a3ec13d33533f017e0"/><file name="Configuration.php" hash="66d648cf736d5410f26fd15f12d6f9c7"/><file name="Cron.php" hash="a7296d26862df0d382023d33496bb80a"/><dir name="Exception"><file name="BadFilePathException.php" hash="68135da8dfe2f0589a531b4bd36e3330"/></dir><file name="Image.php" hash="d9ff80e2bf61fdad36a496437ff2ee1d"/><file name="Logger.php" hash="59671974f707abbed687e88f8d6a3b35"/><file name="MagentoFolderTranslator.php" hash="37219fc1804d6ad8d1686af8509e1963"/><file name="Migration.php" hash="30f671877307d93904fd823d01d35c1d"/><file name="MigrationError.php" hash="67eca6725679a5dae6eab65efae39c64"/><dir name="Observer"><file name="Config.php" hash="4f07c81f36b2d198673627b4bca12e39"/><file name="Product.php" hash="e52cf2454b7ccb23f1a0cbc7c2cd8a6b"/><file name="System.php" hash="29a76486ce525dbd844935b5b8000835"/></dir><dir name="Resource"><dir name="Cms"><dir name="Synchronisation"><file name="Collection.php" hash="226db91ad96a348f0d937781358f9dec"/></dir></dir><dir name="Media"><file name="Collection.php" hash="f54d914a6f79c7b3ab51f822bf64de39"/></dir><file name="Migration.php" hash="69a545d0627016afc03ea097641aa749"/><dir name="MigrationError"><file name="Collection.php" hash="3c5ef530b18b4cd7763a610b84cd3d41"/></dir><file name="MigrationError.php" hash="e6de24a80cb0daed6ead44c699dce535"/><dir name="Synchronisation"><file name="Collection.php" hash="d16275121feb30e57b9b54122e26f05c"/></dir><file name="Synchronisation.php" hash="5b721d854d8f89bc3310e46081be7153"/></dir><file name="Synchronisation.php" hash="05414c5959efc7656b8e101617005d9a"/><file name="SynchronisedMediaUnifier.php" hash="4467ead90fe094ecbea9657266984492"/><file name="SynchronizationChecker.php" hash="35e9c5ad347357d92e921e65056303a6"/><dir name="System"><dir name="Config"><file name="Free.php" hash="a4c47b0b5d60d2e40d12975c98d69eae"/><dir name="Source"><dir name="Dropdown"><file name="Dpr.php" hash="2b9bfd5f836dbdb5d7224d298264f540"/><file name="Gravity.php" hash="c241498e2093640892170673cd7550cd"/><file name="Quality.php" hash="09920e6156a1d6088879cdcea616e312"/></dir></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="CloudinaryController.php" hash="2dede30a95297addc9a4542ce758262d"/><file name="CloudinaryajaxController.php" hash="b862b92cacb10cc81b2edb03a010b5e6"/><file name="CloudinarylogController.php" hash="6178610f821e3d2a51985c45136b8ab1"/><file name="CloudinaryresetController.php" hash="c86108b6f9deaef13bbbc7a021bcd277"/></dir></dir><dir name="data"><dir name="cloudinary_setup"><file name="data-upgrade-0.1.0-0.1.1.php" hash="4c6ce6cd9ab0d94654afb4a398fb3d6c"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="ce3689d26ca0e8a4b74ce683c245e716"/><file name="config.xml" hash="eec85d1de7212e3c024bb55e31258089"/><file name="system.xml" hash="43325a790e33ceffde1429f588395cc1"/></dir><dir name="sql"><dir name="cloudinary_setup"><file name="install-0.1.0.php" hash="55d93b3dab573c2a932edbb5a2fa4865"/><file name="upgrade-0.1.0-0.1.1.php" hash="6c8d430fbf7b9714586b67db3d455008"/><file name="upgrade-1.1.3-1.1.4.php" hash="d6314fc1843b2061d0d04ae60c4d8091"/><file name="upgrade-1.1.4-1.1.5.php" hash="5b035e4b600cbbc743e9ff6a7b505230"/><file name="upgrade-1.1.5-1.1.6.php" hash="323c5e50635018be420cf524072f6a92"/><file name="upgrade-2.0.0-2.1.0.php" hash="9d053bed5099e064eed808a090755b03"/><file name="upgrade-2.1.0-2.5.0.php" hash="641c9aae29e22a54f52c6913e874cd56"/><file name="upgrade-2.5.0-2.6.0.php" hash="b38da8fbc177b9a64e3ba25fca434d00"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Cloudinary_Cloudinary.xml" hash="9337962a4ccf8a43164d5d71dfd2d756"/></dir></target><target name="magelib"><dir name="CloudinaryExtension"><dir name="AutoUploadMapping"><file name="ApiClient.php" hash="cc7417a53b73c92509736959727cc3d9"/><file name="Configuration.php" hash="0c28915836a4d7ba4390f2831c86aa6f"/><file name="RequestProcessor.php" hash="ef82cf531a21b4879b9facadd8085070"/></dir><file name="Cloud.php" hash="59b0debf9ae297e4e824e39ba819b1d1"/><file name="CloudinaryImageManager.php" hash="94af20e7b144adc4a27ee011aabbefe3"/><file name="CloudinaryImageProvider.php" hash="c13ba73cc22f2e7c738676f746d146bc"/><file name="ConfigurationBuilder.php" hash="c8832b207d9228ef14b3c74100ee74c4"/><file name="ConfigurationInterface.php" hash="4129b1e282fb0000b78946f07baa740c"/><file name="CredentialValidator.php" hash="965b0bd024f668aabcc9f30ef2e3c240"/><file name="Credentials.php" hash="71054eb4af7b6496608ffd14912bdbe4"/><dir name="Exception"><file name="ApiError.php" hash="d6fb1e32ca96183e9800c3706de37206"/><file name="FileExists.php" hash="6969387c67deef15a378cb94b9d269ac"/><file name="InvalidCredentials.php" hash="abecc635a25f6c9896c605ad16e1f7d7"/><file name="MigrationError.php" hash="92ea7aa65f4e14e606fa107d33f3ad30"/></dir><file name="FolderTranslator.php" hash="19a335acf751d67bd7efe46829602490"/><dir name="Image"><file name="ImageFactory.php" hash="0a2e066331584d33a9c4ec03787fd6e5"/><file name="LocalImage.php" hash="ab9b814b1a006baf05b9904af3ebce74"/><file name="Synchronizable.php" hash="b842f71ed25718838233207b7748f1bf"/><file name="SynchronizationChecker.php" hash="f2c45545766a81fede68138cf84dd1af"/><dir name="Transformation"><file name="Crop.php" hash="84e57281780a57326c938ac776641e8b"/><file name="Dimensions.php" hash="86a36c564aa41a08da2cf383d611c060"/><file name="Dpr.php" hash="f78cd1bfabaf3088ca8d4af972bfd453"/><file name="FetchFormat.php" hash="c745a6d80b509755cb6ae9fe37b95d76"/><file name="Freeform.php" hash="fdcbcea659f8908af54f30492b306fb5"/><file name="Gravity.php" hash="c1c2adf4dbbeaa6b06d67d2014300559"/><file name="Quality.php" hash="23a857f3910aecf6e45645194ff7f54e"/></dir><file name="Transformation.php" hash="f117d3117900e42d00a0e64461c2a771"/></dir><file name="Image.php" hash="3090cfbaa3b2a90b5ef4a2a94b165581"/><file name="ImageInterface.php" hash="4a7c7e39d7fda0b0fa99affcac78ec8c"/><file name="ImageProvider.php" hash="a615c472cdc8a6ad7d887133db35c262"/><dir name="Migration"><file name="BatchUploader.php" hash="87d9dcf1c07fb9975283d7e4f577f1b9"/><file name="Logger.php" hash="648b47bb065de0c81b386ac300b4f9a3"/><file name="Queue.php" hash="add92864192b0950c29c91ffe5e5a3ee"/><file name="SynchronizedMediaRepository.php" hash="6b4e07f253aad9b845c68d51a1ab4166"/><file name="Task.php" hash="ac11d06c531d48b38cf88f6e8f2bdc19"/></dir><dir name="Security"><file name="ApiSignature.php" hash="049c7db2684ec2a6cf5bb4efcd064951"/><file name="CloudinaryEnvironmentVariable.php" hash="418af61bdbcfef955df29ac47c54415b"/><file name="ConsoleUrl.php" hash="4e748cfe0f5a0aeab2307c623179c6f9"/><file name="EnvironmentVariable.php" hash="297fa60b819ffc028b9a32dae6eef63d"/><file name="Key.php" hash="ac3a50b59f2a7db1edcf30386759c7ec"/><file name="Secret.php" hash="b1010679976575d57752dbb07f1b94ed"/><file name="SignedConsoleUrl.php" hash="791e1f1080be23423c2ad87f431f6221"/></dir><file name="SynchroniseAssetsRepositoryInterface.php" hash="e0d8e270ae2c74214e82e53e04e3dc0f"/><file name="UploadConfig.php" hash="a68f1ea7b84574ec36a8d2fac9bd6054"/><file name="UploadResponseValidator.php" hash="2d20dba12898b277b20b010d24f18859"/><file name="UrlGenerator.php" hash="06d223e5628c68570a2af4f8fb2306ce"/><file name="ValidateRemoteUrlRequest.php" hash="c2e2eb712e5293ad508a23610dfbbd6d"/></dir><dir name="Cloudinary"><file name="Api.php" hash="6595974e7fe061bdbb343943c1a975b2"/><file name="AuthToken.php" hash="bec8b856baf85d89a249c932c3eba39f"/><file name="Cloudinary.php" hash="f9b22b842d8dcabfd291a4d3021286a3"/><file name="CloudinaryField.php" hash="411714580d21b58115ab07737367173a"/><file name="Helpers.php" hash="4db8371fc84d34be49c8ea04eee7d6eb"/><file name="PreloadedFile.php" hash="73cc9e276f96553814f05eae592d11ee"/><file name="Search.php" hash="775a02974591dc1b95a084c501a372cf"/><file name="Uploader.php" hash="485a4bc302b36c5f55e189f696019a33"/><file name="cacert.pem" hash="c4290b9deb70d0bef2f88b67fc68c8ec"/></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="cloudinary"><file name="cloudinary.xml" hash="871fd14e699e5ee23d2a44cd2332abd7"/></dir></dir><dir name="template"><dir name="cloudinary"><file name="log.phtml" hash="ca027cf9501afc17dda51355c0243771"/><file name="manage.phtml" hash="7f20f5013e2a716561f445636f3bed13"/><file name="reset.phtml" hash="6c13650ef05118b7fd06b0907c7a34ae"/><dir name="system"><dir name="config"><file name="free.phtml" hash="8b7cfc3cf8a2b6e86fbf71e3c49f902f"/><file name="signup.phtml" hash="2a0e06990eb542f22531ac2ebb5996f5"/></dir></dir></dir></dir></dir></dir></dir></target></contents>
19
  <compatible/>
20
  <dependencies><required><php><min>5.4.0</min><max>7.1.0</max></php></required></dependencies>
21
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Cloudinary_Cloudinary</name>
4
+ <version>2.8.1</version>
5
  <stability>stable</stability>
6
  <license>MIT License (MITL)</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Cloudinary - Image Management In The Cloud</summary>
10
  <description>Cloudinary supercharges your images! Upload images to the cloud, deliver optimized via a fast CDN, perform smart resizing and apply effects.</description>
11
+ <notes> - Chain resizing after free transforms&#xD;
 
 
12
  </notes>
13
  <authors><author><name>Cloudinary</name><user>cloudinary</user><email>accounts+magento@cloudinary.com</email></author></authors>
14
+ <date>2017-07-05</date>
15
+ <time>14:22:52</time>
16
+ <contents><target name="magecommunity"><dir name="Cloudinary"><dir name="Cloudinary"><dir name="Block"><dir name="Adminhtml"><dir name="Catalog"><dir name="Product"><dir name="Edit"><file name="Gallery.php" hash="696fc9b6fa6dc375c5fb22c5c0ce6fb4"/><file name="Tab.php" hash="1977e332b9395e739ebcf23fa7f1651b"/></dir></dir></dir><dir name="Log"><file name="Grid.php" hash="1f8c277b31e21a8d28bcb57716a9a1f7"/></dir><file name="Log.php" hash="d76ab8c1f2ab39137a2726437c6e487a"/><dir name="Manage"><file name="Grid.php" hash="b6a05f6ba08c5ba0d08846a7b0a06776"/></dir><file name="Manage.php" hash="8a86244c9810cde1e4a297d5ce84cce4"/><dir name="Page"><file name="Menu.php" hash="891d6a4c075ba03c9a20658076c86ad0"/></dir><dir name="Reset"><dir name="Edit"><file name="Form.php" hash="059109b8230f9404921fb53660fdb228"/></dir><file name="Edit.php" hash="6944d440bcedcef8d8d118ecb2e61019"/></dir><dir name="System"><dir name="Config"><dir name="Form"><file name="Free.php" hash="33a3aff8e241d6ca142c6dfb59c1a90b"/></dir><file name="Signup.php" hash="ed6accbe7a4ce16bb0679eaf0c2dbb22"/></dir></dir></dir></dir><dir name="Helper"><file name="Autoloader.php" hash="393b3e2fc25e63ca28157152d2542b18"/><file name="Config.php" hash="737331dc824063845b8b908c0d18f04c"/><file name="Console.php" hash="7c909e3226c51c05d6da1f6ff9cbbfc9"/><file name="Cron.php" hash="805557370a2006b15444b7a62bbbc65a"/><file name="Data.php" hash="42c9d44f1bbe530e30cf5379846dea65"/><file name="Image.php" hash="bb528465df282eb5beb2c106207d8670"/><file name="Reset.php" hash="0525cbbe861889f840e6a75dc991fb2a"/></dir><dir name="Model"><file name="AdminProductObserver.php" hash="a288bb758b481efe9b34e32ca69c3927"/><dir name="AutoUploadMapping"><file name="Configuration.php" hash="a9c2e1176ec36cea6f5183b24793dc2d"/></dir><file name="Cache.php" hash="7ddc224dd71b05120a4431502ce20d8d"/><dir name="Catalog"><dir name="Product"><file name="Image.php" hash="b5d14bcb836158890152c9fed191f8bc"/><dir name="Media"><file name="Config.php" hash="b2458dde388c9be83a8e592ee58c566f"/></dir><file name="Media.php" hash="05726616a07d7d08933e9654e6107283"/></dir></dir><dir name="Cms"><dir name="Adminhtml"><dir name="Template"><file name="Filter.php" hash="792893f6b4e884a8e42847d457a6068c"/></dir></dir><file name="Synchronisation.php" hash="8d830a18f169a0ff5f7d865e3afcb710"/><dir name="Template"><file name="Filter.php" hash="c3fe64f98128043de13e92156a26ab02"/></dir><file name="Uploader.php" hash="69d6855309eb35d78c532e4789d6d526"/><dir name="Wysiwyg"><dir name="Images"><file name="Storage.php" hash="0d23e557d6db06308886d9307fe92665"/></dir></dir></dir><file name="CollectionCounter.php" hash="e69953aee5d966a3ec13d33533f017e0"/><file name="Configuration.php" hash="f0775edab155bc1d706ee7bf95e1dd99"/><file name="Cron.php" hash="a7296d26862df0d382023d33496bb80a"/><dir name="Exception"><file name="BadFilePathException.php" hash="68135da8dfe2f0589a531b4bd36e3330"/></dir><file name="Image.php" hash="d9ff80e2bf61fdad36a496437ff2ee1d"/><file name="Logger.php" hash="59671974f707abbed687e88f8d6a3b35"/><file name="MagentoFolderTranslator.php" hash="37219fc1804d6ad8d1686af8509e1963"/><file name="Migration.php" hash="30f671877307d93904fd823d01d35c1d"/><file name="MigrationError.php" hash="67eca6725679a5dae6eab65efae39c64"/><dir name="Observer"><file name="Config.php" hash="4f07c81f36b2d198673627b4bca12e39"/><file name="Product.php" hash="e52cf2454b7ccb23f1a0cbc7c2cd8a6b"/><file name="System.php" hash="29a76486ce525dbd844935b5b8000835"/></dir><dir name="Resource"><dir name="Cms"><dir name="Synchronisation"><file name="Collection.php" hash="226db91ad96a348f0d937781358f9dec"/></dir></dir><dir name="Media"><file name="Collection.php" hash="f54d914a6f79c7b3ab51f822bf64de39"/></dir><file name="Migration.php" hash="69a545d0627016afc03ea097641aa749"/><dir name="MigrationError"><file name="Collection.php" hash="3c5ef530b18b4cd7763a610b84cd3d41"/></dir><file name="MigrationError.php" hash="e6de24a80cb0daed6ead44c699dce535"/><dir name="Synchronisation"><file name="Collection.php" hash="d16275121feb30e57b9b54122e26f05c"/></dir><file name="Synchronisation.php" hash="5b721d854d8f89bc3310e46081be7153"/><dir name="Transformation"><file name="Collection.php" hash="c5aade73f0e9d8aed8f8f07a723e699a"/></dir><file name="Transformation.php" hash="83eb0abf83a234d923c58b78a49ffe0d"/></dir><file name="Synchronisation.php" hash="05414c5959efc7656b8e101617005d9a"/><file name="SynchronisedMediaUnifier.php" hash="4467ead90fe094ecbea9657266984492"/><file name="SynchronizationChecker.php" hash="16bfa55ef032d0cc0295c04d237905d8"/><dir name="System"><dir name="Config"><file name="Free.php" hash="8627ffbefd95ab46e9115157753d9bb9"/><dir name="Source"><dir name="Dropdown"><file name="Dpr.php" hash="2b9bfd5f836dbdb5d7224d298264f540"/><file name="Gravity.php" hash="d1e75d61364f5df26cc4b46140d747b4"/><file name="Quality.php" hash="09920e6156a1d6088879cdcea616e312"/></dir></dir></dir></dir><file name="Transformation.php" hash="2f7a031d05da3a0e76964cd0e586507d"/></dir><dir name="controllers"><dir name="Adminhtml"><file name="CloudinaryController.php" hash="a0be09a2454c1db87fc87220b7c10aa4"/><file name="CloudinaryajaxController.php" hash="3160aefb1aa0d2797654ce4481111aac"/><file name="CloudinarylogController.php" hash="6178610f821e3d2a51985c45136b8ab1"/><file name="CloudinaryproductController.php" hash="6ca23f6eb7e20635954d3075d0421d69"/><file name="CloudinaryresetController.php" hash="c86108b6f9deaef13bbbc7a021bcd277"/></dir></dir><dir name="data"><dir name="cloudinary_setup"><file name="data-upgrade-0.1.0-0.1.1.php" hash="4c6ce6cd9ab0d94654afb4a398fb3d6c"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="ce3689d26ca0e8a4b74ce683c245e716"/><file name="config.xml" hash="0ec0c94e83e4062a8f89b4fd4a7771e1"/><file name="system.xml" hash="118c7d7c69a15480765eb29c0b596423"/></dir><dir name="sql"><dir name="cloudinary_setup"><file name="install-0.1.0.php" hash="55d93b3dab573c2a932edbb5a2fa4865"/><file name="upgrade-0.1.0-0.1.1.php" hash="6c8d430fbf7b9714586b67db3d455008"/><file name="upgrade-1.1.3-1.1.4.php" hash="d6314fc1843b2061d0d04ae60c4d8091"/><file name="upgrade-1.1.4-1.1.5.php" hash="5b035e4b600cbbc743e9ff6a7b505230"/><file name="upgrade-1.1.5-1.1.6.php" hash="323c5e50635018be420cf524072f6a92"/><file name="upgrade-2.0.0-2.1.0.php" hash="9d053bed5099e064eed808a090755b03"/><file name="upgrade-2.1.0-2.5.0.php" hash="641c9aae29e22a54f52c6913e874cd56"/><file name="upgrade-2.5.0-2.6.0.php" hash="b38da8fbc177b9a64e3ba25fca434d00"/><file name="upgrade-2.6.0-2.7.0.php" hash="641c9aae29e22a54f52c6913e874cd56"/><file name="upgrade-2.7.0-2.8.0.php" hash="f383c11939990f020e1381d79ef20ef0"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Cloudinary_Cloudinary.xml" hash="9337962a4ccf8a43164d5d71dfd2d756"/></dir></target><target name="magelib"><dir name="CloudinaryExtension"><dir name="AutoUploadMapping"><file name="ApiClient.php" hash="cc7417a53b73c92509736959727cc3d9"/><file name="Configuration.php" hash="0c28915836a4d7ba4390f2831c86aa6f"/><file name="RequestProcessor.php" hash="ef82cf531a21b4879b9facadd8085070"/></dir><file name="Cloud.php" hash="59b0debf9ae297e4e824e39ba819b1d1"/><file name="CloudinaryImageManager.php" hash="94af20e7b144adc4a27ee011aabbefe3"/><file name="CloudinaryImageProvider.php" hash="c13ba73cc22f2e7c738676f746d146bc"/><file name="ConfigurationBuilder.php" hash="c8832b207d9228ef14b3c74100ee74c4"/><file name="ConfigurationInterface.php" hash="4129b1e282fb0000b78946f07baa740c"/><file name="CredentialValidator.php" hash="965b0bd024f668aabcc9f30ef2e3c240"/><file name="Credentials.php" hash="71054eb4af7b6496608ffd14912bdbe4"/><dir name="Exception"><file name="ApiError.php" hash="d6fb1e32ca96183e9800c3706de37206"/><file name="FileExists.php" hash="6969387c67deef15a378cb94b9d269ac"/><file name="InvalidCredentials.php" hash="abecc635a25f6c9896c605ad16e1f7d7"/><file name="MigrationError.php" hash="92ea7aa65f4e14e606fa107d33f3ad30"/></dir><file name="FolderTranslator.php" hash="19a335acf751d67bd7efe46829602490"/><dir name="Image"><file name="ImageFactory.php" hash="0a2e066331584d33a9c4ec03787fd6e5"/><file name="LocalImage.php" hash="ab9b814b1a006baf05b9904af3ebce74"/><file name="Synchronizable.php" hash="b842f71ed25718838233207b7748f1bf"/><file name="SynchronizationChecker.php" hash="f2c45545766a81fede68138cf84dd1af"/><dir name="Transformation"><file name="Crop.php" hash="84e57281780a57326c938ac776641e8b"/><file name="Dimensions.php" hash="86a36c564aa41a08da2cf383d611c060"/><file name="Dpr.php" hash="f78cd1bfabaf3088ca8d4af972bfd453"/><file name="FetchFormat.php" hash="c745a6d80b509755cb6ae9fe37b95d76"/><file name="Freeform.php" hash="fdcbcea659f8908af54f30492b306fb5"/><file name="Gravity.php" hash="c1c2adf4dbbeaa6b06d67d2014300559"/><file name="Quality.php" hash="23a857f3910aecf6e45645194ff7f54e"/></dir><file name="Transformation.php" hash="63559e079fee65e646394a9396522353"/></dir><file name="Image.php" hash="3090cfbaa3b2a90b5ef4a2a94b165581"/><file name="ImageInterface.php" hash="4a7c7e39d7fda0b0fa99affcac78ec8c"/><file name="ImageProvider.php" hash="a615c472cdc8a6ad7d887133db35c262"/><dir name="Migration"><file name="BatchUploader.php" hash="87d9dcf1c07fb9975283d7e4f577f1b9"/><file name="Logger.php" hash="648b47bb065de0c81b386ac300b4f9a3"/><file name="Queue.php" hash="add92864192b0950c29c91ffe5e5a3ee"/><file name="SynchronizedMediaRepository.php" hash="6b4e07f253aad9b845c68d51a1ab4166"/><file name="Task.php" hash="ac11d06c531d48b38cf88f6e8f2bdc19"/></dir><dir name="Security"><file name="ApiSignature.php" hash="049c7db2684ec2a6cf5bb4efcd064951"/><file name="CloudinaryEnvironmentVariable.php" hash="418af61bdbcfef955df29ac47c54415b"/><file name="ConsoleUrl.php" hash="4e748cfe0f5a0aeab2307c623179c6f9"/><file name="EnvironmentVariable.php" hash="297fa60b819ffc028b9a32dae6eef63d"/><file name="Key.php" hash="ac3a50b59f2a7db1edcf30386759c7ec"/><file name="Secret.php" hash="b1010679976575d57752dbb07f1b94ed"/><file name="SignedConsoleUrl.php" hash="791e1f1080be23423c2ad87f431f6221"/></dir><file name="SynchroniseAssetsRepositoryInterface.php" hash="e0d8e270ae2c74214e82e53e04e3dc0f"/><file name="UploadConfig.php" hash="a68f1ea7b84574ec36a8d2fac9bd6054"/><file name="UploadResponseValidator.php" hash="2d20dba12898b277b20b010d24f18859"/><file name="UrlGenerator.php" hash="06d223e5628c68570a2af4f8fb2306ce"/><file name="ValidateRemoteUrlRequest.php" hash="c2e2eb712e5293ad508a23610dfbbd6d"/></dir><dir name="Cloudinary"><file name="Api.php" hash="6595974e7fe061bdbb343943c1a975b2"/><file name="AuthToken.php" hash="bec8b856baf85d89a249c932c3eba39f"/><file name="Cloudinary.php" hash="f9b22b842d8dcabfd291a4d3021286a3"/><file name="CloudinaryField.php" hash="411714580d21b58115ab07737367173a"/><file name="Helpers.php" hash="4db8371fc84d34be49c8ea04eee7d6eb"/><file name="PreloadedFile.php" hash="73cc9e276f96553814f05eae592d11ee"/><file name="Search.php" hash="775a02974591dc1b95a084c501a372cf"/><file name="Uploader.php" hash="485a4bc302b36c5f55e189f696019a33"/><file name="cacert.pem" hash="c4290b9deb70d0bef2f88b67fc68c8ec"/></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="cloudinary"><file name="cloudinary.xml" hash="4bf8ceae45161a9a5e73f653de3b77e7"/></dir></dir><dir name="template"><dir name="cloudinary"><dir name="catalog"><dir name="product"><file name="gallery.phtml" hash="55e899449844abed9d32464181c834eb"/></dir></dir><file name="log.phtml" hash="ca027cf9501afc17dda51355c0243771"/><file name="manage.phtml" hash="386871ab46a5068e9553df2a2721ba8e"/><file name="reset.phtml" hash="6c13650ef05118b7fd06b0907c7a34ae"/><dir name="system"><dir name="config"><file name="free.phtml" hash="8b7cfc3cf8a2b6e86fbf71e3c49f902f"/><file name="signup.phtml" hash="2a0e06990eb542f22531ac2ebb5996f5"/></dir></dir></dir></dir></dir></dir></dir></target></contents>
17
  <compatible/>
18
  <dependencies><required><php><min>5.4.0</min><max>7.1.0</max></php></required></dependencies>
19
  </package>