From 64b02b9d063e415af3c9a3bc19eff02e749663ab Mon Sep 17 00:00:00 2001 From: pini-girit Date: Wed, 14 Nov 2018 15:33:47 +0200 Subject: [PATCH 1/9] CLOUDINARY-15,CLOUDINARY-11,CLOUDINARY-18: Added support for Use-Root-Path & Version-less URLs (+New 'Advanced' configuration section) --- Core/CloudinaryImageProvider.php | 24 +++++++++++++++--------- Model/Configuration.php | 23 ++++++++++++++++++++++- composer.json | 2 +- etc/adminhtml/system.xml | 13 +++++++++++++ etc/config.xml | 4 ++++ etc/module.xml | 2 +- 6 files changed, 56 insertions(+), 12 deletions(-) diff --git a/Core/CloudinaryImageProvider.php b/Core/CloudinaryImageProvider.php index cbfe356..f54bc3e 100644 --- a/Core/CloudinaryImageProvider.php +++ b/Core/CloudinaryImageProvider.php @@ -3,12 +3,9 @@ namespace Cloudinary\Cloudinary\Core; use Cloudinary; -use Cloudinary\Uploader; use Cloudinary\Cloudinary\Core\Exception\ApiError; use Cloudinary\Cloudinary\Core\Image\Transformation; -use Cloudinary\Cloudinary\Core\Security; -use Cloudinary\Cloudinary\Core\Image\Transformation\Format; -use Cloudinary\Cloudinary\Core\Image\Transformation\FetchFormat; +use Cloudinary\Uploader; class CloudinaryImageProvider implements ImageProvider { @@ -57,7 +54,8 @@ public function __construct( * @param ConfigurationInterface $configuration * @return CloudinaryImageProvider */ - public static function fromConfiguration(ConfigurationInterface $configuration){ + public static function fromConfiguration(ConfigurationInterface $configuration) + { return new CloudinaryImageProvider( $configuration, new ConfigurationBuilder($configuration), @@ -94,10 +92,18 @@ public function upload(Image $image) */ public function retrieveTransformed(Image $image, Transformation $transformation) { - return Image::fromPath( - \cloudinary_url($image->getId(), ['transformation' => $transformation->build(), 'secure' => true]), - $image->getRelativePath() - ); + $imagePath = \cloudinary_url($image->getId(), ['transformation' => $transformation->build(), 'secure' => true]); + + if ($this->configuration->getUseRootPath()) { + $imagePath = str_replace(".com/{$this->configuration->getCloud()}/image/upload/", ".com/{$this->configuration->getCloud()}/", $imagePath); + } + + if ($this->configuration->getRemoveVersionNumber()) { + $regex = '/\/v[0-9]+\/' . preg_quote(ltrim($image->getId(), '/'), '/') . '$/'; + $imagePath = preg_replace($regex, '/' . ltrim($image->getId(), '/'), $imagePath); + } + + return Image::fromPath($imagePath, $image->getRelativePath()); } /** diff --git a/Model/Configuration.php b/Model/Configuration.php index fad16c2..f0b217d 100644 --- a/Model/Configuration.php +++ b/Model/Configuration.php @@ -26,11 +26,16 @@ class Configuration implements ConfigurationInterface const USER_PLATFORM_TEMPLATE = 'CloudinaryMagento/%s (Magento %s)'; const CONFIG_PATH_ENVIRONMENT_VARIABLE = 'cloudinary/setup/cloudinary_environment_variable'; const CONFIG_CDN_SUBDOMAIN = 'cloudinary/configuration/cloudinary_cdn_subdomain'; + // Transformations const CONFIG_DEFAULT_GRAVITY = 'cloudinary/transformations/cloudinary_gravity'; const CONFIG_DEFAULT_QUALITY = 'cloudinary/transformations/cloudinary_image_quality'; const CONFIG_DEFAULT_DPR = 'cloudinary/transformations/cloudinary_image_dpr'; const CONFIG_DEFAULT_FETCH_FORMAT = 'cloudinary/transformations/cloudinary_fetch_format'; const CONFIG_GLOBAL_FREEFORM = 'cloudinary/transformations/cloudinary_free_transform_global'; + // Advanced + const CONFIG_PATH_REMOVE_VERSION_NUMBER = 'cloudinary/advanced/remove_version_number'; + const CONFIG_PATH_USE_ROOT_PATH = 'cloudinary/advanced/use_root_path'; + const USE_FILENAME = true; const UNIQUE_FILENAME = false; const OVERWRITE = false; @@ -132,7 +137,7 @@ public function getCdnSubdomainStatus() */ public function getUserPlatform() { - return sprintf(self::USER_PLATFORM_TEMPLATE, '1.6.0', '2.0.0'); + return sprintf(self::USER_PLATFORM_TEMPLATE, '1.6.2', '2.0.0'); } /** @@ -236,4 +241,20 @@ private function getEnvironmentVariable() } return $this->environmentVariable; } + + /** + * @return bool + */ + public function getRemoveVersionNumber() + { + return (bool) $this->configReader->getValue(self::CONFIG_PATH_REMOVE_VERSION_NUMBER); + } + + /** + * @return bool + */ + public function getUseRootPath() + { + return (bool) $this->configReader->getValue(self::CONFIG_PATH_REMOVE_VERSION_NUMBER); + } } diff --git a/composer.json b/composer.json index 482453f..52c5480 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "cloudinary/magento2-module-cloudinary", "description": "Cloudinary Magento 2 Integration.", "type": "magento2-module", - "version": "1.6.0", + "version": "1.6.2", "minimum-stability": "dev", "license": "MIT", "repositories": { diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index 5175e4a..c87ea35 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -62,6 +62,19 @@ Cloudinary\Cloudinary\Block\Adminhtml\Form\Field\Free + + + + + Remove version number (e.g '/v1/') from URLs + Magento\Config\Model\Config\Source\Yesno + + + + Remove '/image/upload/' from URLs + Magento\Config\Model\Config\Source\Yesno + + diff --git a/etc/config.xml b/etc/config.xml index 7c0f7bd..251673a 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -11,6 +11,10 @@ 1 + + 0 + 0 + diff --git a/etc/module.xml b/etc/module.xml index b350786..c432a3c 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,6 +1,6 @@ - + From 78b9f065a66f10e5a5d54785b0b6b21d277e93e0 Mon Sep 17 00:00:00 2001 From: pini-girit Date: Wed, 14 Nov 2018 16:13:09 +0200 Subject: [PATCH 2/9] CLOUDINARY-15,CLOUDINARY-11,CLOUDINARY-18: Added support for Use-Root-Path & Version-less URLs (+New 'Advanced' configuration section) --- etc/adminhtml/system.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index c87ea35..bc64012 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -62,7 +62,7 @@ Cloudinary\Cloudinary\Block\Adminhtml\Form\Field\Free - + From 0471dff6ab4ad1b326bfbfb0bf9d4c2fcd8b1769 Mon Sep 17 00:00:00 2001 From: pini-girit Date: Wed, 14 Nov 2018 16:48:41 +0200 Subject: [PATCH 3/9] CLOUDINARY-15,CLOUDINARY-11,CLOUDINARY-18: Added support for Use-Root-Path & Version-less URLs (+New 'Advanced' configuration section) --- etc/adminhtml/system.xml | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index bc64012..56dafa9 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -2,76 +2,76 @@ -
+
service Cloudinary_Cloudinary::config_cloudinary - + - + Magento\Config\Model\Config\Source\Yesno - + - + Set the credentials of your Cloudinary account. Copy the "Environment variable" string from the dashboard of Cloudinary's Management Console. Cloudinary\Cloudinary\Model\Config\Backend\Credentials - + - + Enable multiple sub-domains of image delivery URLs for faster page load speed. Magento\Config\Model\Config\Source\Yesno - + When enabled, Cloudinary will fetch images it does not have from your site automatically without requiring the manual migration process. Magento\Config\Model\Config\Source\Yesno - + - + Automatically deliver images converted to modern image formats based on viewing device and browser. For example, deliver WebP on Chrome and JPEG-XR on Internet Explorer for better performance and user experience. Magento\Config\Model\Config\Source\Yesno - + Adjust quality of generated images to balance between visual quality and file size minimization. The quality is relevant for JPEG and WebP compression levels for example. Cloudinary\Cloudinary\Model\Config\Source\Dropdown\Quality - + Define the part of the image to focus on when cropping images in order to better match your graphic design. Cloudinary\Cloudinary\Model\Config\Source\Dropdown\Gravity - + Use DPR value higher than 1.0 to generate and deliver hi-res images for better visual result on HiDPI devices, such as Retina Display devices (e.g., 2.0). Cloudinary\Cloudinary\Model\Config\Source\Dropdown\Dpr - + Cloudinary\Cloudinary\Model\Config\Backend\Free Cloudinary\Cloudinary\Block\Adminhtml\Form\Field\Free - + - + - Remove version number (e.g '/v1/') from URLs + Remove version number (e.g., ".../v1/...") from URLs Magento\Config\Model\Config\Source\Yesno - + - Remove '/image/upload/' from URLs + Remove "/image/upload/" from URLs Magento\Config\Model\Config\Source\Yesno From 660b8ac8f342465794a5aa82a2d593db1efe02f6 Mon Sep 17 00:00:00 2001 From: pini-girit Date: Thu, 15 Nov 2018 09:51:58 +0200 Subject: [PATCH 4/9] CLOUDINARY-7: Fixed 'Use auto mapping...' observer on admin system configuration + Added some logics for multistore cases (not sure if it's needed or globally supported) --- Core/AutoUploadMapping/RequestProcessor.php | 54 ++++++- .../AutoUploadConfiguration.php | 23 +-- Model/Configuration.php | 141 +++++++++++++----- Model/Observer/Configuration.php | 80 +++++++--- 4 files changed, 223 insertions(+), 75 deletions(-) diff --git a/Core/AutoUploadMapping/RequestProcessor.php b/Core/AutoUploadMapping/RequestProcessor.php index b550815..63e644a 100644 --- a/Core/AutoUploadMapping/RequestProcessor.php +++ b/Core/AutoUploadMapping/RequestProcessor.php @@ -2,6 +2,8 @@ namespace Cloudinary\Cloudinary\Core\AutoUploadMapping; +use Magento\Store\Model\ScopeInterface; + class RequestProcessor { /** @@ -14,6 +16,10 @@ class RequestProcessor */ private $apiClient; + protected $scope = ScopeInterface::SCOPE_STORE; + + protected $scopeId = null; + /** * @param AutoUploadConfigurationInterface $configuration * @param ApiClient $apiClient @@ -26,6 +32,46 @@ public function __construct( $this->apiClient = $apiClient; } + /** + * @method setScopeId + * @param string|null $scopeId + * @return $this + */ + public function setScope($scope) + { + $this->scope = $scope; + return $this; + } + + /** + * @method getScope + * @return string|null + */ + public function getScope() + { + return $this->scope; + } + + /** + * @method setScopeId + * @param integer|null $scopeId + * @return $this + */ + public function setScopeId($scopeId) + { + $this->scopeId = $scopeId; + return $this; + } + + /** + * @method getScopeId + * @return integer|null + */ + public function getScopeId($scope) + { + return $this->scopeId; + } + /** * @param string $folder * @param string $url @@ -33,11 +79,11 @@ public function __construct( */ public function handle($folder, $url) { - if ($this->configuration->isActive() == $this->configuration->getRequestState()) { + if ($this->configuration->isActive($this->scope, $this->scopeId) == $this->configuration->getRequestState($this->scope, $this->scopeId)) { return true; } - if ($this->configuration->getRequestState() == AutoUploadConfigurationInterface::ACTIVE) { + if ($this->configuration->getRequestState($this->scope, $this->scopeId) == AutoUploadConfigurationInterface::ACTIVE) { return $this->handleActiveRequest($folder, $url); } @@ -56,9 +102,9 @@ private function handleActiveRequest($folder, $url) $result = $this->apiClient->prepareMapping($folder, $url); if ($result) { - $this->configuration->setState(AutoUploadConfigurationInterface::ACTIVE); + $this->configuration->setState(AutoUploadConfigurationInterface::ACTIVE, $this->scope, $this->scopeId); } else { - $this->configuration->setRequestState(AutoUploadConfigurationInterface::INACTIVE); + $this->configuration->setRequestState(AutoUploadConfigurationInterface::INACTIVE, $this->scope, $this->scopeId); } return $result; diff --git a/Model/AutoUploadMapping/AutoUploadConfiguration.php b/Model/AutoUploadMapping/AutoUploadConfiguration.php index 697c8a5..29aaffe 100644 --- a/Model/AutoUploadMapping/AutoUploadConfiguration.php +++ b/Model/AutoUploadMapping/AutoUploadConfiguration.php @@ -2,9 +2,10 @@ namespace Cloudinary\Cloudinary\Model\AutoUploadMapping; +use Cloudinary\Cloudinary\Core\AutoUploadMapping\AutoUploadConfigurationInterface; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Config\Storage\WriterInterface; -use Cloudinary\Cloudinary\Core\AutoUploadMapping\AutoUploadConfigurationInterface; +use Magento\Store\Model\ScopeInterface; class AutoUploadConfiguration implements AutoUploadConfigurationInterface { @@ -38,41 +39,41 @@ public function __construct( /** * @return bool */ - public function isActive() + public function isActive($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - return $this->configReader->isSetFlag(self::STATE_PATH); + return $this->configReader->isSetFlag(self::STATE_PATH, $scope, $scopeId); } /** * @param bool $state */ - public function setState($state) + public function setState($state, $scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - $this->setFlag(self::STATE_PATH, $state); + $this->setFlag(self::STATE_PATH, $state, $scope, $scopeId); } /** * @return bool */ - public function getRequestState() + public function getRequestState($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - return $this->configReader->isSetFlag(self::REQUEST_PATH); + return $this->configReader->isSetFlag(self::REQUEST_PATH, $scope, $scopeId); } /** * @param bool $state */ - public function setRequestState($state) + public function setRequestState($state, $scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - $this->setFlag(self::REQUEST_PATH, $state); + $this->setFlag(self::REQUEST_PATH, $state, $scope, $scopeId); } /** * @param string $key * @param bool $state */ - private function setFlag($key, $state) + private function setFlag($key, $state, $scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - $this->configWriter->save($key, $state ? self::CONFIG_TRUE : self::CONFIG_FALSE); + $this->configWriter->save($key, $state ? self::CONFIG_TRUE : self::CONFIG_FALSE, $scope, $scopeId); } } diff --git a/Model/Configuration.php b/Model/Configuration.php index f0b217d..0b86a89 100644 --- a/Model/Configuration.php +++ b/Model/Configuration.php @@ -19,6 +19,7 @@ use Magento\Framework\App\Config\Storage\WriterInterface; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Encryption\EncryptorInterface; +use Magento\Store\Model\ScopeInterface; class Configuration implements ConfigurationInterface { @@ -26,15 +27,19 @@ class Configuration implements ConfigurationInterface const USER_PLATFORM_TEMPLATE = 'CloudinaryMagento/%s (Magento %s)'; const CONFIG_PATH_ENVIRONMENT_VARIABLE = 'cloudinary/setup/cloudinary_environment_variable'; const CONFIG_CDN_SUBDOMAIN = 'cloudinary/configuration/cloudinary_cdn_subdomain'; - // Transformations + //= Transformations const CONFIG_DEFAULT_GRAVITY = 'cloudinary/transformations/cloudinary_gravity'; const CONFIG_DEFAULT_QUALITY = 'cloudinary/transformations/cloudinary_image_quality'; const CONFIG_DEFAULT_DPR = 'cloudinary/transformations/cloudinary_image_dpr'; const CONFIG_DEFAULT_FETCH_FORMAT = 'cloudinary/transformations/cloudinary_fetch_format'; const CONFIG_GLOBAL_FREEFORM = 'cloudinary/transformations/cloudinary_free_transform_global'; - // Advanced + //= Advanced const CONFIG_PATH_REMOVE_VERSION_NUMBER = 'cloudinary/advanced/remove_version_number'; const CONFIG_PATH_USE_ROOT_PATH = 'cloudinary/advanced/use_root_path'; + //= Others + const CONFIG_PATH_SECURE_BASE_URL = "web/secure/base_url"; + const CONFIG_PATH_UNSECURE_BASE_URL = "web/unsecure/base_url"; + const CONFIG_PATH_USE_SECURE_IN_FRONTEND = "web/secure/use_in_frontend"; const USE_FILENAME = true; const UNIQUE_FILENAME = false; @@ -90,46 +95,46 @@ public function __construct( /** * @return Cloud */ - public function getCloud() + public function getCloud($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - return $this->getEnvironmentVariable()->getCloud(); + return $this->getEnvironmentVariable($scope, $scopeId)->getCloud(); } /** * @return Credentials */ - public function getCredentials() + public function getCredentials($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - return $this->getEnvironmentVariable()->getCredentials(); + return $this->getEnvironmentVariable($scope, $scopeId)->getCredentials(); } /** * @return Transformation */ - public function getDefaultTransformation() + public function getDefaultTransformation($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { return Transformation::builder() - ->withGravity(Gravity::fromString($this->getDefaultGravity())) - ->withQuality(Quality::fromString($this->getImageQuality())) - ->withFetchFormat(FetchFormat::fromString($this->getFetchFormat())) - ->withFreeform(Freeform::fromString($this->getDefaultGlobalFreeform())) - ->withDpr(Dpr::fromString($this->getImageDpr())); + ->withGravity(Gravity::fromString($this->getDefaultGravity($scope, $scopeId))) + ->withQuality(Quality::fromString($this->getImageQuality($scope, $scopeId))) + ->withFetchFormat(FetchFormat::fromString($this->getFetchFormat($scope, $scopeId))) + ->withFreeform(Freeform::fromString($this->getDefaultGlobalFreeform($scope, $scopeId))) + ->withDpr(Dpr::fromString($this->getImageDpr($scope, $scopeId))); } /** * @return string */ - private function getDefaultGlobalFreeform() + private function getDefaultGlobalFreeform($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - return (string) $this->configReader->getValue(self::CONFIG_GLOBAL_FREEFORM); + return (string) $this->configReader->getValue(self::CONFIG_GLOBAL_FREEFORM, $scope, $scopeId); } /** * @return boolean */ - public function getCdnSubdomainStatus() + public function getCdnSubdomainStatus($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - return $this->configReader->isSetFlag(self::CONFIG_CDN_SUBDOMAIN); + return $this->configReader->isSetFlag(self::CONFIG_CDN_SUBDOMAIN, $scope, $scopeId); } /** @@ -151,19 +156,19 @@ public function getUploadConfig() /** * @return boolean */ - public function isEnabled() + public function isEnabled($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - return $this->hasEnvironmentVariable() && $this->configReader->isSetFlag(self::CONFIG_PATH_ENABLED); + return $this->hasEnvironmentVariable() && $this->configReader->isSetFlag(self::CONFIG_PATH_ENABLED, $scope, $scopeId); } - public function enable() + public function enable($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - $this->configWriter->save(self::CONFIG_PATH_ENABLED, self::SCOPE_ID_ONE); + $this->configWriter->save(self::CONFIG_PATH_ENABLED, self::SCOPE_ID_ONE, $scope, $scopeId); } - public function disable() + public function disable($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - $this->configWriter->save(self::CONFIG_PATH_ENABLED, self::SCOPE_ID_ZERO); + $this->configWriter->save(self::CONFIG_PATH_ENABLED, self::SCOPE_ID_ZERO, $scope, $scopeId); } /** @@ -186,53 +191,53 @@ public function getMigratedPath($file) /** * @return string */ - public function getDefaultGravity() + public function getDefaultGravity($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - return (string) $this->configReader->getValue(self::CONFIG_DEFAULT_GRAVITY); + return (string) $this->configReader->getValue(self::CONFIG_DEFAULT_GRAVITY, $scope, $scopeId); } /** * @return string */ - public function getFetchFormat() + public function getFetchFormat($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - return $this->configReader->isSetFlag(self::CONFIG_DEFAULT_FETCH_FORMAT) ? FetchFormat::FETCH_FORMAT_AUTO : ''; + return $this->configReader->isSetFlag(self::CONFIG_DEFAULT_FETCH_FORMAT, $scope, $scopeId) ? FetchFormat::FETCH_FORMAT_AUTO : ''; } /** * @return string */ - public function getImageQuality() + public function getImageQuality($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - return $this->configReader->getValue(self::CONFIG_DEFAULT_QUALITY); + return $this->configReader->getValue(self::CONFIG_DEFAULT_QUALITY, $scope, $scopeId); } /** * @return string */ - public function getImageDpr() + public function getImageDpr($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - return $this->configReader->getValue(self::CONFIG_DEFAULT_DPR); + return $this->configReader->getValue(self::CONFIG_DEFAULT_DPR, $scope, $scopeId); } /** * @return bool */ - public function hasEnvironmentVariable() + public function hasEnvironmentVariable($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - return (bool)$this->configReader->getValue(self::CONFIG_PATH_ENVIRONMENT_VARIABLE); + return (bool)$this->configReader->getValue(self::CONFIG_PATH_ENVIRONMENT_VARIABLE, $scope, $scopeId); } /** * @return CloudinaryEnvironmentVariable */ - private function getEnvironmentVariable() + private function getEnvironmentVariable($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { if (is_null($this->environmentVariable)) { try { $this->environmentVariable = CloudinaryEnvironmentVariable::fromString( $this->decryptor->decrypt( - $this->configReader->getValue(self::CONFIG_PATH_ENVIRONMENT_VARIABLE) + $this->configReader->getValue(self::CONFIG_PATH_ENVIRONMENT_VARIABLE, $scope, $scopeId) ) ); } catch (InvalidCredentials $invalidConfigException) { @@ -245,16 +250,76 @@ private function getEnvironmentVariable() /** * @return bool */ - public function getRemoveVersionNumber() + public function getRemoveVersionNumber($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - return (bool) $this->configReader->getValue(self::CONFIG_PATH_REMOVE_VERSION_NUMBER); + return (bool) $this->configReader->getValue(self::CONFIG_PATH_REMOVE_VERSION_NUMBER, $scope, $scopeId); } /** * @return bool */ - public function getUseRootPath() + public function getUseRootPath($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) { - return (bool) $this->configReader->getValue(self::CONFIG_PATH_REMOVE_VERSION_NUMBER); + return (bool) $this->configReader->getValue(self::CONFIG_PATH_REMOVE_VERSION_NUMBER, $scope, $scopeId); + } + + /** + * @method getUseSecureInFrontend + * @param string $scope + * @param integer|null $scopeId + * @return string + */ + public function getUseSecureInFrontend($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + { + return ($this->configReader->getValue(self::CONFIG_PATH_USE_SECURE_IN_FRONTEND, $scope, $scopeId)) ? true : false; + } + + /** + * @method getSecureBaseUrl + * @param string $path + * @param string $scope + * @param integer|null $scopeId + * @return string + */ + public function getSecureBaseUrl($path = "", $scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + { + $return = (string) $this->configReader->getValue(self::CONFIG_PATH_SECURE_BASE_URL, $scope, $scopeId); + return rtrim($return, "/") . "/" . ltrim($path, "/"); + } + + /** + * @method getUnsecureBaseUrl + * @param string $path + * @param string $scope + * @param integer|null $scopeId + * @return string + */ + public function getUnsecureBaseUrl($path = "", $scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + { + $return = (string) $this->configReader->getValue(self::CONFIG_PATH_UNSECURE_BASE_URL, $scope, $scopeId); + return rtrim($return, "/") . "/" . ltrim($path, "/"); + } + + /** + * @method getBaseUrl + * @param string $path + * @param string $scope + * @param integer|null $scopeId + * @return string + */ + public function getBaseUrl($path = "", $scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + { + return ($this->getUseSecureInFrontend($scope, $scopeId)) ? $this->getSecureBaseUrl($path, $scope, $scopeId) : $this->getUnsecureBaseUrl($path, $scope, $scopeId); + } + + /** + * @method getMediaBaseUrl + * @param string $scope + * @param integer|null $scopeId + * @return string + */ + public function getMediaBaseUrl($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + { + return $this->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA, $scope, $scopeId); } } diff --git a/Model/Observer/Configuration.php b/Model/Observer/Configuration.php index b0a7274..9372cb6 100644 --- a/Model/Observer/Configuration.php +++ b/Model/Observer/Configuration.php @@ -2,13 +2,12 @@ namespace Cloudinary\Cloudinary\Model\Observer; -use Cloudinary\Cloudinary\Core\CloudinaryImageManager; -use Magento\Framework\App\ObjectManager; +use Cloudinary\Cloudinary\Core\AutoUploadMapping\RequestProcessor; +use Magento\Framework\App\Cache\TypeListInterface; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; -use Cloudinary\Cloudinary\Core\AutoUploadMapping\RequestProcessor; use Magento\Framework\Message\ManagerInterface; -use Magento\Framework\UrlInterface; +use Magento\Store\Model\ScopeInterface; class Configuration implements ObserverInterface { @@ -17,23 +16,67 @@ class Configuration implements ObserverInterface /** * @var RequestProcessor */ - private $requestProcessor; + protected $requestProcessor; /** * @var ManagerInterface */ - private $messageManager; + protected $messageManager; + + /** + * @var \Cloudinary\Cloudinary\Model\Configuration + */ + protected $configuration; + + /** + * @var TypeListInterface + */ + protected $cacheTypeList; + + protected $scope = ScopeInterface::SCOPE_STORE; + protected $scopeId = null; + protected $changedPaths = []; /** * @param RequestProcessor $requestProcessor * @param ManagerInterface $messageManager + * @param \Cloudinary\Cloudinary\Model\Configuration $configuration + * @param TypeListInterface $cacheTypeList */ public function __construct( RequestProcessor $requestProcessor, - ManagerInterface $messageManager + ManagerInterface $messageManager, + \Cloudinary\Cloudinary\Model\Configuration $configuration, + TypeListInterface $cacheTypeList ) { $this->requestProcessor = $requestProcessor; $this->messageManager = $messageManager; + $this->configuration = $configuration; + $this->cacheTypeList = $cacheTypeList; + } + + protected function _init(Observer $observer) + { + //Clear config cache if needed + $this->changedPaths = (array) $observer->getEvent()->getChangedPaths(); + if (in_array($this->changedPaths, [ + \Cloudinary\Cloudinary\Model\Configuration::CONFIG_PATH_ENABLED, + \Cloudinary\Cloudinary\Model\Configuration::CONFIG_PATH_ENVIRONMENT_VARIABLE, + \Cloudinary\Cloudinary\Model\AutoUploadMapping\AutoUploadConfiguration::REQUEST_PATH + ])) { + $this->cleanConfigCache(); + } + + //Get current configuration scope from request & inject to requestProcessor. + $this->scopeId = $observer->getEvent()->getStore(); + $this->scope = ScopeInterface::SCOPE_STORE; + if (!$this->scopeId && ($this->scopeId = $observer->getEvent()->getWebsite())) { + $this->scope = ScopeInterface::SCOPE_WEBSITE; + } + if (!$this->scopeId) { + $this->scope = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT; + } + $this->requestProcessor->setScope($this->scope)->setScopeId($this->scopeId); } /** @@ -41,24 +84,17 @@ public function __construct( */ public function execute(Observer $observer) { - if (!$this->requestProcessor->handle('media', $this->getMediaBaseUrl())) { + $this->_init($observer); + + if (!$this->requestProcessor->handle('media', $this->configuration->getMediaBaseUrl($this->scope, $this->scopeId))) { $this->messageManager->addErrorMessage(self::AUTO_UPLOAD_SETUP_FAIL_MESSAGE); } } - /** - * @return string - */ - function getMediaBaseUrl() { - /** @var \Magento\Framework\ObjectManagerInterface $om */ - $om = ObjectManager::getInstance(); - - /** @var \Magento\Store\Model\StoreManagerInterface $storeManager */ - $storeManager = $om->get('Magento\Store\Model\StoreManagerInterface'); - - /** @var \Magento\Store\Api\Data\StoreInterface|\Magento\Store\Model\Store $currentStore */ - $currentStore = $storeManager->getStore(); - - return $currentStore->getBaseUrl(UrlInterface::URL_TYPE_MEDIA); + protected function cleanConfigCache() + { + $this->_cacheTypeList->cleanType(\Magento\Framework\App\Cache\Type\Config::TYPE_IDENTIFIER); + $this->_cacheTypeList->cleanType(\Magento\PageCache\Model\Cache\Type::TYPE_IDENTIFIER); + return $this; } } From db1915af68236894ab4ee571a0ddb460476bbd17 Mon Sep 17 00:00:00 2001 From: pini-girit Date: Thu, 22 Nov 2018 12:09:37 +0200 Subject: [PATCH 5/9] CLOUDINARY-3: Removed website & store scopes from system.xml & cleaned store/website specific configurations (only supports default at the moment). Moved Cloudinary tab outside of Services & added Cloudinary's icon. Made sure that the config cache will be automatically deleted before mapping the media dir after changing the value of cloudinary_auto_upload_mapping_request --- .../AutoUploadConfiguration.php | 21 ++-- Model/Configuration.php | 105 ++++++++---------- Model/Observer/Configuration.php | 29 +---- Model/Template/Filter.php | 4 +- Setup/UpgradeData.php | 52 +++++++++ composer.json | 2 +- etc/adminhtml/system.xml | 37 +++--- etc/module.xml | 2 +- view/adminhtml/web/css/source/_module.less | 11 ++ view/base/web/images/cloudinary_icon.png | Bin 0 -> 2714 bytes 10 files changed, 149 insertions(+), 114 deletions(-) create mode 100644 Setup/UpgradeData.php create mode 100644 view/adminhtml/web/css/source/_module.less create mode 100644 view/base/web/images/cloudinary_icon.png diff --git a/Model/AutoUploadMapping/AutoUploadConfiguration.php b/Model/AutoUploadMapping/AutoUploadConfiguration.php index 29aaffe..55d3cdb 100644 --- a/Model/AutoUploadMapping/AutoUploadConfiguration.php +++ b/Model/AutoUploadMapping/AutoUploadConfiguration.php @@ -5,7 +5,6 @@ use Cloudinary\Cloudinary\Core\AutoUploadMapping\AutoUploadConfigurationInterface; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Config\Storage\WriterInterface; -use Magento\Store\Model\ScopeInterface; class AutoUploadConfiguration implements AutoUploadConfigurationInterface { @@ -39,41 +38,41 @@ public function __construct( /** * @return bool */ - public function isActive($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function isActive() { - return $this->configReader->isSetFlag(self::STATE_PATH, $scope, $scopeId); + return $this->configReader->isSetFlag(self::STATE_PATH); } /** * @param bool $state */ - public function setState($state, $scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function setState($state) { - $this->setFlag(self::STATE_PATH, $state, $scope, $scopeId); + $this->setFlag(self::STATE_PATH, $state); } /** * @return bool */ - public function getRequestState($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getRequestState() { - return $this->configReader->isSetFlag(self::REQUEST_PATH, $scope, $scopeId); + return $this->configReader->isSetFlag(self::REQUEST_PATH); } /** * @param bool $state */ - public function setRequestState($state, $scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function setRequestState($state) { - $this->setFlag(self::REQUEST_PATH, $state, $scope, $scopeId); + $this->setFlag(self::REQUEST_PATH, $state); } /** * @param string $key * @param bool $state */ - private function setFlag($key, $state, $scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + private function setFlag($key, $state) { - $this->configWriter->save($key, $state ? self::CONFIG_TRUE : self::CONFIG_FALSE, $scope, $scopeId); + $this->configWriter->save($key, $state ? self::CONFIG_TRUE : self::CONFIG_FALSE); } } diff --git a/Model/Configuration.php b/Model/Configuration.php index 0b86a89..c666cbc 100644 --- a/Model/Configuration.php +++ b/Model/Configuration.php @@ -19,7 +19,6 @@ use Magento\Framework\App\Config\Storage\WriterInterface; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Encryption\EncryptorInterface; -use Magento\Store\Model\ScopeInterface; class Configuration implements ConfigurationInterface { @@ -95,46 +94,46 @@ public function __construct( /** * @return Cloud */ - public function getCloud($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getCloud() { - return $this->getEnvironmentVariable($scope, $scopeId)->getCloud(); + return $this->getEnvironmentVariable()->getCloud(); } /** * @return Credentials */ - public function getCredentials($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getCredentials() { - return $this->getEnvironmentVariable($scope, $scopeId)->getCredentials(); + return $this->getEnvironmentVariable()->getCredentials(); } /** * @return Transformation */ - public function getDefaultTransformation($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getDefaultTransformation() { return Transformation::builder() - ->withGravity(Gravity::fromString($this->getDefaultGravity($scope, $scopeId))) - ->withQuality(Quality::fromString($this->getImageQuality($scope, $scopeId))) - ->withFetchFormat(FetchFormat::fromString($this->getFetchFormat($scope, $scopeId))) - ->withFreeform(Freeform::fromString($this->getDefaultGlobalFreeform($scope, $scopeId))) - ->withDpr(Dpr::fromString($this->getImageDpr($scope, $scopeId))); + ->withGravity(Gravity::fromString($this->getDefaultGravity())) + ->withQuality(Quality::fromString($this->getImageQuality())) + ->withFetchFormat(FetchFormat::fromString($this->getFetchFormat())) + ->withFreeform(Freeform::fromString($this->getDefaultGlobalFreeform())) + ->withDpr(Dpr::fromString($this->getImageDpr())); } /** * @return string */ - private function getDefaultGlobalFreeform($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + private function getDefaultGlobalFreeform() { - return (string) $this->configReader->getValue(self::CONFIG_GLOBAL_FREEFORM, $scope, $scopeId); + return (string) $this->configReader->getValue(self::CONFIG_GLOBAL_FREEFORM); } /** * @return boolean */ - public function getCdnSubdomainStatus($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getCdnSubdomainStatus() { - return $this->configReader->isSetFlag(self::CONFIG_CDN_SUBDOMAIN, $scope, $scopeId); + return $this->configReader->isSetFlag(self::CONFIG_CDN_SUBDOMAIN); } /** @@ -142,7 +141,7 @@ public function getCdnSubdomainStatus($scope = ScopeInterface::SCOPE_STORE, $sco */ public function getUserPlatform() { - return sprintf(self::USER_PLATFORM_TEMPLATE, '1.6.2', '2.0.0'); + return sprintf(self::USER_PLATFORM_TEMPLATE, '1.6.3', '2.0.0'); } /** @@ -156,19 +155,19 @@ public function getUploadConfig() /** * @return boolean */ - public function isEnabled($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function isEnabled() { - return $this->hasEnvironmentVariable() && $this->configReader->isSetFlag(self::CONFIG_PATH_ENABLED, $scope, $scopeId); + return $this->hasEnvironmentVariable() && $this->configReader->isSetFlag(self::CONFIG_PATH_ENABLED); } - public function enable($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function enable() { - $this->configWriter->save(self::CONFIG_PATH_ENABLED, self::SCOPE_ID_ONE, $scope, $scopeId); + $this->configWriter->save(self::CONFIG_PATH_ENABLED, self::SCOPE_ID_ONE); } - public function disable($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function disable() { - $this->configWriter->save(self::CONFIG_PATH_ENABLED, self::SCOPE_ID_ZERO, $scope, $scopeId); + $this->configWriter->save(self::CONFIG_PATH_ENABLED, self::SCOPE_ID_ZERO); } /** @@ -191,53 +190,53 @@ public function getMigratedPath($file) /** * @return string */ - public function getDefaultGravity($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getDefaultGravity() { - return (string) $this->configReader->getValue(self::CONFIG_DEFAULT_GRAVITY, $scope, $scopeId); + return (string) $this->configReader->getValue(self::CONFIG_DEFAULT_GRAVITY); } /** * @return string */ - public function getFetchFormat($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getFetchFormat() { - return $this->configReader->isSetFlag(self::CONFIG_DEFAULT_FETCH_FORMAT, $scope, $scopeId) ? FetchFormat::FETCH_FORMAT_AUTO : ''; + return $this->configReader->isSetFlag(self::CONFIG_DEFAULT_FETCH_FORMAT) ? FetchFormat::FETCH_FORMAT_AUTO : ''; } /** * @return string */ - public function getImageQuality($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getImageQuality() { - return $this->configReader->getValue(self::CONFIG_DEFAULT_QUALITY, $scope, $scopeId); + return $this->configReader->getValue(self::CONFIG_DEFAULT_QUALITY); } /** * @return string */ - public function getImageDpr($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getImageDpr() { - return $this->configReader->getValue(self::CONFIG_DEFAULT_DPR, $scope, $scopeId); + return $this->configReader->getValue(self::CONFIG_DEFAULT_DPR); } /** * @return bool */ - public function hasEnvironmentVariable($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function hasEnvironmentVariable() { - return (bool)$this->configReader->getValue(self::CONFIG_PATH_ENVIRONMENT_VARIABLE, $scope, $scopeId); + return (bool)$this->configReader->getValue(self::CONFIG_PATH_ENVIRONMENT_VARIABLE); } /** * @return CloudinaryEnvironmentVariable */ - private function getEnvironmentVariable($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + private function getEnvironmentVariable() { if (is_null($this->environmentVariable)) { try { $this->environmentVariable = CloudinaryEnvironmentVariable::fromString( $this->decryptor->decrypt( - $this->configReader->getValue(self::CONFIG_PATH_ENVIRONMENT_VARIABLE, $scope, $scopeId) + $this->configReader->getValue(self::CONFIG_PATH_ENVIRONMENT_VARIABLE) ) ); } catch (InvalidCredentials $invalidConfigException) { @@ -250,76 +249,66 @@ private function getEnvironmentVariable($scope = ScopeInterface::SCOPE_STORE, $s /** * @return bool */ - public function getRemoveVersionNumber($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getRemoveVersionNumber() { - return (bool) $this->configReader->getValue(self::CONFIG_PATH_REMOVE_VERSION_NUMBER, $scope, $scopeId); + return (bool) $this->configReader->getValue(self::CONFIG_PATH_REMOVE_VERSION_NUMBER); } /** * @return bool */ - public function getUseRootPath($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getUseRootPath() { - return (bool) $this->configReader->getValue(self::CONFIG_PATH_REMOVE_VERSION_NUMBER, $scope, $scopeId); + return (bool) $this->configReader->getValue(self::CONFIG_PATH_REMOVE_VERSION_NUMBER); } /** * @method getUseSecureInFrontend - * @param string $scope - * @param integer|null $scopeId * @return string */ - public function getUseSecureInFrontend($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getUseSecureInFrontend() { - return ($this->configReader->getValue(self::CONFIG_PATH_USE_SECURE_IN_FRONTEND, $scope, $scopeId)) ? true : false; + return ($this->configReader->getValue(self::CONFIG_PATH_USE_SECURE_IN_FRONTEND)) ? true : false; } /** * @method getSecureBaseUrl * @param string $path - * @param string $scope - * @param integer|null $scopeId * @return string */ - public function getSecureBaseUrl($path = "", $scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getSecureBaseUrl($path = "") { - $return = (string) $this->configReader->getValue(self::CONFIG_PATH_SECURE_BASE_URL, $scope, $scopeId); + $return = (string) $this->configReader->getValue(self::CONFIG_PATH_SECURE_BASE_URL); return rtrim($return, "/") . "/" . ltrim($path, "/"); } /** * @method getUnsecureBaseUrl * @param string $path - * @param string $scope - * @param integer|null $scopeId * @return string */ - public function getUnsecureBaseUrl($path = "", $scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getUnsecureBaseUrl($path = "") { - $return = (string) $this->configReader->getValue(self::CONFIG_PATH_UNSECURE_BASE_URL, $scope, $scopeId); + $return = (string) $this->configReader->getValue(self::CONFIG_PATH_UNSECURE_BASE_URL); return rtrim($return, "/") . "/" . ltrim($path, "/"); } /** * @method getBaseUrl * @param string $path - * @param string $scope - * @param integer|null $scopeId * @return string */ - public function getBaseUrl($path = "", $scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getBaseUrl($path = "") { - return ($this->getUseSecureInFrontend($scope, $scopeId)) ? $this->getSecureBaseUrl($path, $scope, $scopeId) : $this->getUnsecureBaseUrl($path, $scope, $scopeId); + return ($this->getUseSecureInFrontend()) ? $this->getSecureBaseUrl($path) : $this->getUnsecureBaseUrl($path); } /** * @method getMediaBaseUrl - * @param string $scope - * @param integer|null $scopeId * @return string */ - public function getMediaBaseUrl($scope = ScopeInterface::SCOPE_STORE, $scopeId = null) + public function getMediaBaseUrl() { - return $this->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA, $scope, $scopeId); + return $this->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA); } } diff --git a/Model/Observer/Configuration.php b/Model/Observer/Configuration.php index 9372cb6..b060417 100644 --- a/Model/Observer/Configuration.php +++ b/Model/Observer/Configuration.php @@ -7,7 +7,6 @@ use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; use Magento\Framework\Message\ManagerInterface; -use Magento\Store\Model\ScopeInterface; class Configuration implements ObserverInterface { @@ -33,8 +32,6 @@ class Configuration implements ObserverInterface */ protected $cacheTypeList; - protected $scope = ScopeInterface::SCOPE_STORE; - protected $scopeId = null; protected $changedPaths = []; /** @@ -55,7 +52,10 @@ public function __construct( $this->cacheTypeList = $cacheTypeList; } - protected function _init(Observer $observer) + /** + * @param Observer $observer + */ + public function execute(Observer $observer) { //Clear config cache if needed $this->changedPaths = (array) $observer->getEvent()->getChangedPaths(); @@ -67,26 +67,7 @@ protected function _init(Observer $observer) $this->cleanConfigCache(); } - //Get current configuration scope from request & inject to requestProcessor. - $this->scopeId = $observer->getEvent()->getStore(); - $this->scope = ScopeInterface::SCOPE_STORE; - if (!$this->scopeId && ($this->scopeId = $observer->getEvent()->getWebsite())) { - $this->scope = ScopeInterface::SCOPE_WEBSITE; - } - if (!$this->scopeId) { - $this->scope = \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT; - } - $this->requestProcessor->setScope($this->scope)->setScopeId($this->scopeId); - } - - /** - * @param Observer $observer - */ - public function execute(Observer $observer) - { - $this->_init($observer); - - if (!$this->requestProcessor->handle('media', $this->configuration->getMediaBaseUrl($this->scope, $this->scopeId))) { + if (!$this->requestProcessor->handle('media', $this->configuration->getMediaBaseUrl())) { $this->messageManager->addErrorMessage(self::AUTO_UPLOAD_SETUP_FAIL_MESSAGE); } } diff --git a/Model/Template/Filter.php b/Model/Template/Filter.php index 316c187..c916eac 100644 --- a/Model/Template/Filter.php +++ b/Model/Template/Filter.php @@ -2,9 +2,9 @@ namespace Cloudinary\Cloudinary\Model\Template; -use Magento\Widget\Model\Template\Filter as WidgetFilter; use Cloudinary\Cloudinary\Core\Image\ImageFactory; use Cloudinary\Cloudinary\Core\UrlGenerator; +use Magento\Widget\Model\Template\Filter as WidgetFilter; class Filter extends WidgetFilter { @@ -92,7 +92,7 @@ public function mediaDirective($construction) $image = $this->imageFactory->build( $params['url'], - function() use ($storeManager, $params) { + function () use ($storeManager, $params) { return sprintf( '%s%s', $storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA), diff --git a/Setup/UpgradeData.php b/Setup/UpgradeData.php new file mode 100644 index 0000000..e499e6a --- /dev/null +++ b/Setup/UpgradeData.php @@ -0,0 +1,52 @@ +_resourceConnection = $resourceConnection; + } + + /** + * {@inheritdoc} + */ + public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + { + $setup->startSetup(); + + if (version_compare($context->getVersion(), '0.6.3') < 0) { + echo "- Reseting configurations for 'website' & 'store' scopes (only supports 'default' at the moment).\n"; + $this->_resourceConnection->getConnection()->delete( + $this->_resourceConnection->getTableName('core_config_data'), + "path LIKE 'cloudinary/%' AND scope != 'default'" + ); + } + + $setup->endSetup(); + } +} diff --git a/composer.json b/composer.json index 52c5480..947b51b 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "cloudinary/magento2-module-cloudinary", "description": "Cloudinary Magento 2 Integration.", "type": "magento2-module", - "version": "1.6.2", + "version": "1.6.3", "minimum-stability": "dev", "license": "MIT", "repositories": { diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index 56dafa9..58e36b6 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -2,9 +2,12 @@ -
- - service + + + +
+ + cloudinary Cloudinary_Cloudinary::config_cloudinary @@ -13,63 +16,63 @@ Magento\Config\Model\Config\Source\Yesno - + - + Set the credentials of your Cloudinary account. Copy the "Environment variable" string from the dashboard of Cloudinary's Management Console. Cloudinary\Cloudinary\Model\Config\Backend\Credentials - + - + Enable multiple sub-domains of image delivery URLs for faster page load speed. Magento\Config\Model\Config\Source\Yesno - + When enabled, Cloudinary will fetch images it does not have from your site automatically without requiring the manual migration process. Magento\Config\Model\Config\Source\Yesno - + - + Automatically deliver images converted to modern image formats based on viewing device and browser. For example, deliver WebP on Chrome and JPEG-XR on Internet Explorer for better performance and user experience. Magento\Config\Model\Config\Source\Yesno - + Adjust quality of generated images to balance between visual quality and file size minimization. The quality is relevant for JPEG and WebP compression levels for example. Cloudinary\Cloudinary\Model\Config\Source\Dropdown\Quality - + Define the part of the image to focus on when cropping images in order to better match your graphic design. Cloudinary\Cloudinary\Model\Config\Source\Dropdown\Gravity - + Use DPR value higher than 1.0 to generate and deliver hi-res images for better visual result on HiDPI devices, such as Retina Display devices (e.g., 2.0). Cloudinary\Cloudinary\Model\Config\Source\Dropdown\Dpr - + Cloudinary\Cloudinary\Model\Config\Backend\Free Cloudinary\Cloudinary\Block\Adminhtml\Form\Field\Free - + - + Remove version number (e.g., ".../v1/...") from URLs Magento\Config\Model\Config\Source\Yesno - + Remove "/image/upload/" from URLs Magento\Config\Model\Config\Source\Yesno diff --git a/etc/module.xml b/etc/module.xml index c432a3c..6814263 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,6 +1,6 @@ - + diff --git a/view/adminhtml/web/css/source/_module.less b/view/adminhtml/web/css/source/_module.less new file mode 100644 index 0000000..0a1e9b7 --- /dev/null +++ b/view/adminhtml/web/css/source/_module.less @@ -0,0 +1,11 @@ +.cloudinary-icon { + background-image: url('Cloudinary_Cloudinary::images/cloudinary_icon.png'); + background-size: contain; + background-repeat: no-repeat; + background-position: center center; + display: inline-block; + width: 22px; + height: 22px; + margin-right: 5px; + vertical-align: middle; +} diff --git a/view/base/web/images/cloudinary_icon.png b/view/base/web/images/cloudinary_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..36f40545b123a05048d57da40d48d0abb7a1bd2e GIT binary patch literal 2714 zcmaJ@c|4T)AD`NvJ0WS=wmfF6vpJ2)3`5L}D1&AcTG1R2#xXNyCI+dWB2+@fqEc3= zoH<&OtEgmkU}H4oNF?h@uFdfqZMDBYe*K=;>v_J%>-~OzuJ<2Lf~)gRRplR)ArOeF zqXU^HTcNA3qP*-&*r{?~w&;i`9wIu=R}{t&fDl_Yj|l>f!3;l;1~S;;A&)^T2;@5h zj+=+bgX% z1OLhQe+moT!ucSQ1`2tH1T5L$d||7h_ym#wWQceIHy$tOOBY@Jc_N*F^uius7^=RUL`swxNB}! zo!zxZf7)*V|K_(OA3?{(icOkQS1W>+CEfe_>_=;@MHmiN2ZAE)n%C`IqHQ4L#ocZ%If%*j;0Ly>5qfdBDn=sq4G- zN^9QwZJ#Qs#7Ro^7E$};Lfs!whPpJL{&5YjZPVIseNYPZX_8k@*wojmW&F_5b5I}m z9NxVDFA=gZYX;D;8!_YqQV)$V z=Oo^We%%)9BsKcai6(tjYcu=D)Lcx+dW{jMsT$0bTV=hJTiw(I6Jj{-gY-|=uJP3A zqz%aA4b-ER%KvyF(tcq=b zFx=Vx2v<3C>ic@d-vYVgIH~5T6CYp46||qLix_(`#*ETrnQNuB@$!pJkoJS%wVBO) zmiYG!`2)Kf@IEc@W!u!5)>%rhRcWr2KPJCFUmvK()Mi9qG?o__fG2ekI$@J4>fwnN zcGoIM>@@4F1JUQ4;U<)3ZNr})(v1+8pm(x?g5`?r3#|3iZ=3lKo~OYThAY+T1aP7C zlB0DNJ&*3-qR(u8`4h1ZZd#)w>9}xtu27*c_1-Qxe%mC^epg16-CTTI&3?VIdV*$0 z=bxTNslBQVI`9Rb>VvmVI+cp@90n|6W;Mp8&uGhiMT_0BI!H;esn3nnw!?zg%u$<1 zG-h&#_Atf=d%Q4iRO-B?Fj6^T@Eo5~B}pY#D4aM7O)0HG0;O}|+K+ns&`bsO6<1ZK zl_yVpe-3m#9baOh@!&%ZetUs}r^`#Wkv2AFwc{*vRpQ8{q1%LERJx_ zesnCROSran{7gxkxqV|!hLw(Ck>>lbt>ue5eMq5>y5eqzT?v!*9GZT{F^IqrPolOhqf3BQSr|Q`s_56Oir+IuzwdjhXIckO|9e%I??kvLdm zR#^Dd9)3(K+QH>pGB{HV5{oQhMUPSMpd|_t&kpGoQ;&RqA zX4o$QayHkrLYuQ}Gu9TD#{IDe*IeJj`m6Dh;y`+vP&09bQGA|?X+J_bOeHWy`WC;$ zx7?k$v1TEcx%4lC{4N(~g6+n*jo5s=2z&YN-e(T#;pRuJ9B)zkya#4zDP%c4mDi^N z>b;$t4jVabi2lIkE^MsY?CRg5BgL6q JWOwk`e*l5er;Pvr literal 0 HcmV?d00001 From 359e85567be6aca22b36f13f68dc2f2594c22065 Mon Sep 17 00:00:00 2001 From: pini-girit Date: Sun, 25 Nov 2018 14:16:50 +0200 Subject: [PATCH 6/9] CLOUDINARY-3: Fixed media dir mapping --- Model/Configuration.php | 54 +++++++++-------------------------------- 1 file changed, 11 insertions(+), 43 deletions(-) diff --git a/Model/Configuration.php b/Model/Configuration.php index c666cbc..3a9447a 100644 --- a/Model/Configuration.php +++ b/Model/Configuration.php @@ -19,6 +19,7 @@ use Magento\Framework\App\Config\Storage\WriterInterface; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Encryption\EncryptorInterface; +use Magento\Store\Model\StoreManagerInterface; class Configuration implements ConfigurationInterface { @@ -71,24 +72,32 @@ class Configuration implements ConfigurationInterface */ private $autoUploadConfiguration; + /** + * @var StoreManagerInterface + */ + private $storeManager; + /** * @param ScopeConfigInterface $configReader * @param WriterInterface $configWriter * @param EncryptorInterface $decryptor * @param AutoUploadConfigurationInterface $autoUploadConfiguration + * @param StoreManagerInterface $storeManager */ public function __construct( ScopeConfigInterface $configReader, WriterInterface $configWriter, EncryptorInterface $decryptor, AutoUploadConfigurationInterface $autoUploadConfiguration, - \Psr\Log\LoggerInterface $logger + \Psr\Log\LoggerInterface $logger, + StoreManagerInterface $storeManager ) { $this->configReader = $configReader; $this->configWriter = $configWriter; $this->decryptor = $decryptor; $this->autoUploadConfiguration = $autoUploadConfiguration; $this->logger = $logger; + $this->storeManager = $storeManager; } /** @@ -262,53 +271,12 @@ public function getUseRootPath() return (bool) $this->configReader->getValue(self::CONFIG_PATH_REMOVE_VERSION_NUMBER); } - /** - * @method getUseSecureInFrontend - * @return string - */ - public function getUseSecureInFrontend() - { - return ($this->configReader->getValue(self::CONFIG_PATH_USE_SECURE_IN_FRONTEND)) ? true : false; - } - - /** - * @method getSecureBaseUrl - * @param string $path - * @return string - */ - public function getSecureBaseUrl($path = "") - { - $return = (string) $this->configReader->getValue(self::CONFIG_PATH_SECURE_BASE_URL); - return rtrim($return, "/") . "/" . ltrim($path, "/"); - } - - /** - * @method getUnsecureBaseUrl - * @param string $path - * @return string - */ - public function getUnsecureBaseUrl($path = "") - { - $return = (string) $this->configReader->getValue(self::CONFIG_PATH_UNSECURE_BASE_URL); - return rtrim($return, "/") . "/" . ltrim($path, "/"); - } - - /** - * @method getBaseUrl - * @param string $path - * @return string - */ - public function getBaseUrl($path = "") - { - return ($this->getUseSecureInFrontend()) ? $this->getSecureBaseUrl($path) : $this->getUnsecureBaseUrl($path); - } - /** * @method getMediaBaseUrl * @return string */ public function getMediaBaseUrl() { - return $this->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA); + return $this->storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA); } } From b3c123672c7d3721a18f1e2132d9edb801cdb32e Mon Sep 17 00:00:00 2001 From: pini-girit Date: Sun, 25 Nov 2018 14:38:08 +0200 Subject: [PATCH 7/9] Updated README & replaced Cloudinary logos --- Block/Adminhtml/Product/Edit/NewVideo.php | 2 +- README.md | 16 +- view/adminhtml/web/css/source/_module.less | 2 +- view/base/web/images/cloudinary_icon.png | Bin 2714 -> 0 bytes .../images/cloudinary_icon_for_white_bg.svg | 69 ++++++ .../images/cloudinary_logo_for_white_bg.jpg | Bin 74836 -> 0 bytes .../images/cloudinary_logo_for_white_bg.svg | 188 ++++++++++++++++ .../cloudinary_vertical_logo_for_white_bg.svg | 203 ++++++++++++++++++ 8 files changed, 477 insertions(+), 3 deletions(-) delete mode 100644 view/base/web/images/cloudinary_icon.png create mode 100644 view/base/web/images/cloudinary_icon_for_white_bg.svg delete mode 100644 view/base/web/images/cloudinary_logo_for_white_bg.jpg create mode 100644 view/base/web/images/cloudinary_logo_for_white_bg.svg create mode 100644 view/base/web/images/cloudinary_vertical_logo_for_white_bg.svg diff --git a/Block/Adminhtml/Product/Edit/NewVideo.php b/Block/Adminhtml/Product/Edit/NewVideo.php index d762b3a..9dafd36 100644 --- a/Block/Adminhtml/Product/Edit/NewVideo.php +++ b/Block/Adminhtml/Product/Edit/NewVideo.php @@ -66,7 +66,7 @@ public function getWidgetOptions() 'htmlId' => $this->getHtmlId(), 'youTubeApiKey' => $this->mediaHelper->getYouTubeApiKey(), 'videoSelector' => $this->videoSelector, - 'cloudinaryPlaceholder' => $this->getViewFileUrl('Cloudinary_Cloudinary::images/cloudinary_logo_for_white_bg.jpg') + 'cloudinaryPlaceholder' => $this->getViewFileUrl('Cloudinary_Cloudinary::images/cloudinary_vertical_logo_for_white_bg.svg') ] ); } diff --git a/README.md b/README.md index 0c001a4..34bcf74 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,22 @@ Magento 2 module for integration with Cloudinary. --- +## ✓ Installation (using git & composer) +Run the following command under your Magento 2 root dir: + +``` +git clone https://github.com/cloudinary/cloudinary_magento2 app/code/Cloudinary/Cloudinary +composer require cloudinary/cloudinary_php:1.8.0 +php bin/magento setup:upgrade +php bin/magento setup:di:compile +php bin/magento setup:static-content:deploy +php bin/magento cache:flush +``` + +--- + https://www.cloudinary.com/ Copyright © 2018 Cloudinary. All rights reserved. -![Cloudinary Logo](https://cloudinary-res.cloudinary.com/image/upload/v1538583988/cloudinary_logo_for_white_bg.svg) +![Cloudinary Logo](https://cloudinary-res.cloudinary.com/image/upload/c_scale,w_300/v1/logo/for_white_bg/cloudinary_logo_for_white_bg.svg) diff --git a/view/adminhtml/web/css/source/_module.less b/view/adminhtml/web/css/source/_module.less index 0a1e9b7..75c8abd 100644 --- a/view/adminhtml/web/css/source/_module.less +++ b/view/adminhtml/web/css/source/_module.less @@ -1,5 +1,5 @@ .cloudinary-icon { - background-image: url('Cloudinary_Cloudinary::images/cloudinary_icon.png'); + background-image: url('Cloudinary_Cloudinary::images/cloudinary_icon_for_white_bg.svg'); background-size: contain; background-repeat: no-repeat; background-position: center center; diff --git a/view/base/web/images/cloudinary_icon.png b/view/base/web/images/cloudinary_icon.png deleted file mode 100644 index 36f40545b123a05048d57da40d48d0abb7a1bd2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2714 zcmaJ@c|4T)AD`NvJ0WS=wmfF6vpJ2)3`5L}D1&AcTG1R2#xXNyCI+dWB2+@fqEc3= zoH<&OtEgmkU}H4oNF?h@uFdfqZMDBYe*K=;>v_J%>-~OzuJ<2Lf~)gRRplR)ArOeF zqXU^HTcNA3qP*-&*r{?~w&;i`9wIu=R}{t&fDl_Yj|l>f!3;l;1~S;;A&)^T2;@5h zj+=+bgX% z1OLhQe+moT!ucSQ1`2tH1T5L$d||7h_ym#wWQceIHy$tOOBY@Jc_N*F^uius7^=RUL`swxNB}! zo!zxZf7)*V|K_(OA3?{(icOkQS1W>+CEfe_>_=;@MHmiN2ZAE)n%C`IqHQ4L#ocZ%If%*j;0Ly>5qfdBDn=sq4G- zN^9QwZJ#Qs#7Ro^7E$};Lfs!whPpJL{&5YjZPVIseNYPZX_8k@*wojmW&F_5b5I}m z9NxVDFA=gZYX;D;8!_YqQV)$V z=Oo^We%%)9BsKcai6(tjYcu=D)Lcx+dW{jMsT$0bTV=hJTiw(I6Jj{-gY-|=uJP3A zqz%aA4b-ER%KvyF(tcq=b zFx=Vx2v<3C>ic@d-vYVgIH~5T6CYp46||qLix_(`#*ETrnQNuB@$!pJkoJS%wVBO) zmiYG!`2)Kf@IEc@W!u!5)>%rhRcWr2KPJCFUmvK()Mi9qG?o__fG2ekI$@J4>fwnN zcGoIM>@@4F1JUQ4;U<)3ZNr})(v1+8pm(x?g5`?r3#|3iZ=3lKo~OYThAY+T1aP7C zlB0DNJ&*3-qR(u8`4h1ZZd#)w>9}xtu27*c_1-Qxe%mC^epg16-CTTI&3?VIdV*$0 z=bxTNslBQVI`9Rb>VvmVI+cp@90n|6W;Mp8&uGhiMT_0BI!H;esn3nnw!?zg%u$<1 zG-h&#_Atf=d%Q4iRO-B?Fj6^T@Eo5~B}pY#D4aM7O)0HG0;O}|+K+ns&`bsO6<1ZK zl_yVpe-3m#9baOh@!&%ZetUs}r^`#Wkv2AFwc{*vRpQ8{q1%LERJx_ zesnCROSran{7gxkxqV|!hLw(Ck>>lbt>ue5eMq5>y5eqzT?v!*9GZT{F^IqrPolOhqf3BQSr|Q`s_56Oir+IuzwdjhXIckO|9e%I??kvLdm zR#^Dd9)3(K+QH>pGB{HV5{oQhMUPSMpd|_t&kpGoQ;&RqA zX4o$QayHkrLYuQ}Gu9TD#{IDe*IeJj`m6Dh;y`+vP&09bQGA|?X+J_bOeHWy`WC;$ zx7?k$v1TEcx%4lC{4N(~g6+n*jo5s=2z&YN-e(T#;pRuJ9B)zkya#4zDP%c4mDi^N z>b;$t4jVabi2lIkE^MsY?CRg5BgL6q JWOwk`e*l5er;Pvr diff --git a/view/base/web/images/cloudinary_icon_for_white_bg.svg b/view/base/web/images/cloudinary_icon_for_white_bg.svg new file mode 100644 index 0000000..0dae7c9 --- /dev/null +++ b/view/base/web/images/cloudinary_icon_for_white_bg.svg @@ -0,0 +1,69 @@ + + + + + + + + + + diff --git a/view/base/web/images/cloudinary_logo_for_white_bg.jpg b/view/base/web/images/cloudinary_logo_for_white_bg.jpg deleted file mode 100644 index b448103c3180ab16219c10915cda66206544f5ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74836 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 + + + + + + + + + + + + + + + + + + + + + + diff --git a/view/base/web/images/cloudinary_vertical_logo_for_white_bg.svg b/view/base/web/images/cloudinary_vertical_logo_for_white_bg.svg new file mode 100644 index 0000000..2e4d2e0 --- /dev/null +++ b/view/base/web/images/cloudinary_vertical_logo_for_white_bg.svg @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + From c1b440e5c988ff341f733d33e0a6f288a10e20ce Mon Sep 17 00:00:00 2001 From: pini-girit Date: Sun, 25 Nov 2018 14:51:47 +0200 Subject: [PATCH 8/9] Updated README & replaced Cloudinary logos --- view/adminhtml/web/css/source/_module.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/view/adminhtml/web/css/source/_module.less b/view/adminhtml/web/css/source/_module.less index 75c8abd..5983d59 100644 --- a/view/adminhtml/web/css/source/_module.less +++ b/view/adminhtml/web/css/source/_module.less @@ -5,7 +5,7 @@ background-position: center center; display: inline-block; width: 22px; - height: 22px; + height: 18px; margin-right: 5px; - vertical-align: middle; + vertical-align: text-bottom; } From 8ef1ca09870af5e258e30890f6771bcfeb294386 Mon Sep 17 00:00:00 2001 From: pini-girit Date: Sun, 25 Nov 2018 15:13:19 +0200 Subject: [PATCH 9/9] CLOUDINARY-3,CLOUDINARY-7: Removed unnecessary logics --- Core/AutoUploadMapping/RequestProcessor.php | 54 ++------------------- 1 file changed, 4 insertions(+), 50 deletions(-) diff --git a/Core/AutoUploadMapping/RequestProcessor.php b/Core/AutoUploadMapping/RequestProcessor.php index 63e644a..b550815 100644 --- a/Core/AutoUploadMapping/RequestProcessor.php +++ b/Core/AutoUploadMapping/RequestProcessor.php @@ -2,8 +2,6 @@ namespace Cloudinary\Cloudinary\Core\AutoUploadMapping; -use Magento\Store\Model\ScopeInterface; - class RequestProcessor { /** @@ -16,10 +14,6 @@ class RequestProcessor */ private $apiClient; - protected $scope = ScopeInterface::SCOPE_STORE; - - protected $scopeId = null; - /** * @param AutoUploadConfigurationInterface $configuration * @param ApiClient $apiClient @@ -32,46 +26,6 @@ public function __construct( $this->apiClient = $apiClient; } - /** - * @method setScopeId - * @param string|null $scopeId - * @return $this - */ - public function setScope($scope) - { - $this->scope = $scope; - return $this; - } - - /** - * @method getScope - * @return string|null - */ - public function getScope() - { - return $this->scope; - } - - /** - * @method setScopeId - * @param integer|null $scopeId - * @return $this - */ - public function setScopeId($scopeId) - { - $this->scopeId = $scopeId; - return $this; - } - - /** - * @method getScopeId - * @return integer|null - */ - public function getScopeId($scope) - { - return $this->scopeId; - } - /** * @param string $folder * @param string $url @@ -79,11 +33,11 @@ public function getScopeId($scope) */ public function handle($folder, $url) { - if ($this->configuration->isActive($this->scope, $this->scopeId) == $this->configuration->getRequestState($this->scope, $this->scopeId)) { + if ($this->configuration->isActive() == $this->configuration->getRequestState()) { return true; } - if ($this->configuration->getRequestState($this->scope, $this->scopeId) == AutoUploadConfigurationInterface::ACTIVE) { + if ($this->configuration->getRequestState() == AutoUploadConfigurationInterface::ACTIVE) { return $this->handleActiveRequest($folder, $url); } @@ -102,9 +56,9 @@ private function handleActiveRequest($folder, $url) $result = $this->apiClient->prepareMapping($folder, $url); if ($result) { - $this->configuration->setState(AutoUploadConfigurationInterface::ACTIVE, $this->scope, $this->scopeId); + $this->configuration->setState(AutoUploadConfigurationInterface::ACTIVE); } else { - $this->configuration->setRequestState(AutoUploadConfigurationInterface::INACTIVE, $this->scope, $this->scopeId); + $this->configuration->setRequestState(AutoUploadConfigurationInterface::INACTIVE); } return $result;