From 989abc166253cc1a9575bbca37bfa3c2bf5781cc Mon Sep 17 00:00:00 2001 From: RahatHameed Date: Wed, 27 Sep 2023 14:01:35 +0300 Subject: [PATCH] OXDEV-7356 Extract the ImageResource from Media Signed-off-by: Anton Fedurtsya --- composer.json | 3 +- services.yaml | 2 +- .../Controller/Admin/MediaController.php | 31 +- src/Core/ViewConfig.php | 5 +- src/Image/DataTransfer/ImageSize.php | 27 ++ src/Image/DataTransfer/ImageSizeInterface.php | 9 + src/Image/Service/ImageResource.php | 224 ++++++++++ src/Image/Service/ImageResourceInterface.php | 35 ++ .../Service/ThumbnailGeneratorInterface.php | 22 + .../ThumbnailGeneratorIntervention.php | 43 ++ src/Image/Service/services.yaml | 15 + src/Service/Media.php | 282 ++---------- tests/Integration/Core/ViewConfigTest.php | 17 +- .../ThumbnailGeneratorInterventionTest.php | 112 +++++ tests/Integration/Service/MediaTest.php | 84 ++-- .../Unit/Image/DataTransfer/ImageSizeTest.php | 26 ++ .../Unit/Image/Service/ImageResourceTest.php | 359 +++++++++++++++ tests/Unit/Service/MediaMock.php | 12 +- tests/Unit/Service/MediaTest.php | 420 ++++-------------- 19 files changed, 1083 insertions(+), 645 deletions(-) create mode 100644 src/Image/DataTransfer/ImageSize.php create mode 100644 src/Image/DataTransfer/ImageSizeInterface.php create mode 100644 src/Image/Service/ImageResource.php create mode 100644 src/Image/Service/ImageResourceInterface.php create mode 100644 src/Image/Service/ThumbnailGeneratorInterface.php create mode 100644 src/Image/Service/ThumbnailGeneratorIntervention.php create mode 100644 src/Image/Service/services.yaml create mode 100644 tests/Integration/Image/Service/ThumbnailGeneratorInterventionTest.php create mode 100644 tests/Unit/Image/DataTransfer/ImageSizeTest.php create mode 100644 tests/Unit/Image/Service/ImageResourceTest.php diff --git a/composer.json b/composer.json index 9dc85c3..9fd330a 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,8 @@ "squizlabs/php_codesniffer": "3.*", "phpstan/phpstan": "^1.8.11", "phpunit/phpunit": "^9.6", - "oxid-esales/oxideshop-ce": "dev-b-7.1.x" + "oxid-esales/oxideshop-ce": "dev-b-7.1.x", + "mikey179/vfsstream": "~1.6.8" }, "autoload": { "psr-4": { diff --git a/services.yaml b/services.yaml index e8f1cbf..206bb25 100644 --- a/services.yaml +++ b/services.yaml @@ -1,5 +1,5 @@ imports: - - { resource: src/Thumbnail/Service/services.yaml } + - { resource: src/Image/Service/services.yaml } services: diff --git a/src/Application/Controller/Admin/MediaController.php b/src/Application/Controller/Admin/MediaController.php index 00db5e2..ee33325 100755 --- a/src/Application/Controller/Admin/MediaController.php +++ b/src/Application/Controller/Admin/MediaController.php @@ -9,6 +9,7 @@ use OxidEsales\Eshop\Application\Controller\Admin\AdminDetailsController; use OxidEsales\Eshop\Core\Registry; +use OxidEsales\MediaLibrary\Image\Service\ImageResourceInterface; use OxidEsales\MediaLibrary\Service\Media; use Symfony\Component\Filesystem\Path; @@ -18,6 +19,7 @@ class MediaController extends AdminDetailsController { protected ?Media $mediaService = null; + protected ?ImageResourceInterface $imageResource = null; /** * Current class template name. @@ -43,13 +45,14 @@ public function init() $this->_sFolderId = Registry::getRequest()->getRequestEscapedParameter('folderid'); } - $this->mediaService = $this->getService(Media::class); + $this->mediaService = $this->getService('OxidEsales\MediaLibrary\Service\Media'); + $this->imageResource = $this->getService('OxidEsales\MediaLibrary\Image\Service\ImageResourceInterface'); - $this->mediaService->setFolder($this->_sFolderId); + $this->imageResource->setFolder($this->_sFolderId); - $this->_sUploadDir = $this->mediaService->getMediaPath(); - $this->_sThumbDir = $this->mediaService->getThumbnailPath(); - $this->_iDefaultThumbnailSize = $this->mediaService->getDefaultThumbnailSize(); + $this->_sUploadDir = $this->imageResource->getMediaPath(); + $this->_sThumbDir = $this->imageResource->getThumbnailPath(); + $this->_iDefaultThumbnailSize = $this->imageResource->getDefaultThumbnailSize(); } /** @@ -64,10 +67,10 @@ public function render() $this->_aViewData['aFiles'] = $this->mediaService->getFiles(0, $iShopId); $this->_aViewData['iFileCount'] = $this->mediaService->getFileCount($iShopId); - $this->_aViewData['sResourceUrl'] = $this->mediaService->getMediaUrl(); - $this->_aViewData['sThumbsUrl'] = $this->mediaService->getThumbnailUrl(); - $this->_aViewData['sFoldername'] = $this->mediaService->getFolderName(); - $this->_aViewData['sFolderId'] = $this->_sFolderId; + $this->_aViewData['sResourceUrl'] = $this->imageResource->getMediaUrl(); + $this->_aViewData['sThumbsUrl'] = $this->imageResource->getThumbnailUrl(); + $this->_aViewData['sFoldername'] = $this->imageResource->getFolderName(); + $this->_aViewData['sFolderId'] = $this->imageResource->getFolderId(); $this->_aViewData['sTab'] = Registry::getRequest()->getRequestEscapedParameter('tab'); $request = Registry::getRequest(); @@ -107,7 +110,7 @@ public function upload() $sFileType = $_FILES['file']['type']; $sSourcePath = $_FILES['file']['tmp_name']; - $sDestPath = Path::join($this->mediaService->getMediaPath(), $_FILES['file']['name']); + $sDestPath = Path::join($this->imageResource->getMediaPath(), $_FILES['file']['name']); $aResult = $this->mediaService->uploadMedia($sSourcePath, $sDestPath, $sFileSize, $sFileType, true); $sId = $aResult['id']; @@ -243,7 +246,7 @@ public function rename() 'msg' => $sMsg, 'name' => $sNewName, 'id' => $sNewId, - 'thumb' => $this->mediaService->getThumbnailUrl($sNewName), + 'thumb' => $this->imageResource->getThumbnailUrl($sNewName), ] ); die($sReturn); @@ -320,14 +323,14 @@ public function getBreadcrumb() $aBreadcrumb = []; $oPath = new \stdClass(); - $oPath->active = ($this->mediaService->getFolderName() ? false : true); + $oPath->active = ($this->imageResource->getFolderName() ? false : true); $oPath->name = 'Root'; $aBreadcrumb[] = $oPath; - if ($this->mediaService->getFolderName()) { + if ($this->imageResource->getFolderName()) { $oPath = new \stdClass(); $oPath->active = true; - $oPath->name = $this->mediaService->getFolderName(); + $oPath->name = $this->imageResource->getFolderName(); $aBreadcrumb[] = $oPath; } diff --git a/src/Core/ViewConfig.php b/src/Core/ViewConfig.php index 28bf1c7..8bcff89 100755 --- a/src/Core/ViewConfig.php +++ b/src/Core/ViewConfig.php @@ -23,8 +23,7 @@ class ViewConfig extends ViewConfig_parent { public function getMediaUrl($sFile = '') { - $oMedia = $this->getService(\OxidEsales\MediaLibrary\Service\Media::class); - - return $oMedia->getMediaUrl($sFile); + $imageResource = $this->getService('OxidEsales\MediaLibrary\Image\Service\ImageResourceInterface'); + return $imageResource->getMediaUrl($sFile); } } diff --git a/src/Image/DataTransfer/ImageSize.php b/src/Image/DataTransfer/ImageSize.php new file mode 100644 index 0000000..cb4c455 --- /dev/null +++ b/src/Image/DataTransfer/ImageSize.php @@ -0,0 +1,27 @@ +width; + } + + public function getHeight(): int + { + return $this->height; + } +} diff --git a/src/Image/DataTransfer/ImageSizeInterface.php b/src/Image/DataTransfer/ImageSizeInterface.php new file mode 100644 index 0000000..5d7d4b0 --- /dev/null +++ b/src/Image/DataTransfer/ImageSizeInterface.php @@ -0,0 +1,9 @@ +connection = $connectionProvider->get(); + } + + + public function getFolderName(): string + { + return $this->_sFolderName; + } + + public function setFolderName($sFolderName): void + { + $this->_sFolderName = $sFolderName; + } + + /** + * @deprecated This is temporary solution, it should be removed in next release. + */ + public function getFolderId(): string + { + return $this->_sFolderId; + } + + /** + * @param $sId + * + * @return void + * @throws \OxidEsales\Eshop\Core\Exception\DatabaseConnectionException + */ + private function setFolderNameForFolderId($sId) + { + $iShopId = $this->shopConfig->getActiveShop()->getShopId(); + + $sSelect = "SELECT `DDFILENAME` FROM `ddmedia` WHERE `OXID` = ? AND `DDFILETYPE` = ? AND `OXSHOPID` = ?"; + $folderName = $this->connection->fetchOne($sSelect, [$sId, 'directory', $iShopId]); + $sFolderName = $folderName ?: ''; + + if ($sFolderName) { + $this->setFolderName($sFolderName); + } + } + + public function setFolder($sFolderId = ''): void + { + $this->_sFolderId = $sFolderId; + if ($sFolderId) { + $this->setFolderNameForFolderId($sFolderId); + } + } + + public function getDefaultThumbnailSize(): int + { + return $this->defaultThumbnailSize; + } + + public function getThumbName($sFile, ?ImageSizeInterface $imageSize = null, $thumbnailCrop = true): string + { + $imageSize = $this->getDefaultImageSizeIfNotProvided($imageSize); + $imageSizeString = sprintf( + '%d*%d%s%s', + $imageSize->getWidth(), + $imageSize->getHeight(), + $thumbnailCrop ? '' : '_nocrop', + '.jpg' + ); + return str_replace('.', '_', md5(basename($sFile))) . '_thumb_' . $imageSizeString; + } + + public function getThumbnailUrl($sFile = '', ?ImageSizeInterface $imageSize = null, $thumbnailCrop = true): string + { + if (!$sFile) { + return $this->getMediaUrl('thumbs/'); + } + + $imageSize = $this->getDefaultImageSizeIfNotProvided($imageSize); + $sThumbName = $this->getThumbName($sFile, $imageSize, $thumbnailCrop); + if (!is_file($this->getThumbnailPath($sThumbName))) { + $sThumbName = $this->createThumbnail($sFile, $imageSize, $thumbnailCrop); + } + if (is_file($this->getThumbnailPath($sThumbName))) { + return $this->getMediaUrl('thumbs/' . $sThumbName); + } + + return false; + } + + public function getThumbnailPath($filename = ''): string + { + return Path::join($this->getMediaPath(), 'thumbs', $filename); + } + + /** + * todo: exception in place of bool response + */ + public function getMediaUrl($filename = '') + { + $filepath = $this->getMediaPath($filename); + + if ($this->isAlternativeImageUrlConfigured()) { + return $filepath; + } + + if (!is_readable($filepath)) { + return false; + } + + if (strpos($filename, 'thumbs/') === false) { + $filename = basename($filename); + } + + return Path::join( + $this->shopConfig->getSslShopUrl(), + self::MEDIA_PATH, + (isset($this->_sFolderName) ? $this->_sFolderName . '/' : ''), + $filename + ); + } + + public function getMediaPath($filename = '', $blDoNotSetFolder = false): string + { + if (!$blDoNotSetFolder) { + $this->checkAndSetFolderName($filename); + } + + $sPath = $this->getPathToMediaFiles() . '/' . ($this->_sFolderName ? $this->_sFolderName . '/' : ''); + + if ($filename) { + return $sPath . (strpos($filename, 'thumbs/') !== false ? $filename : basename($filename)); + } + + return $sPath; + } + + public function createThumbnail($sFileName, ?ImageSizeInterface $imageSize = null, $thumbnailCrop = true) + { + $sFilePath = $this->getMediaPath($sFileName, true); + if (is_readable($sFilePath)) { + $imageSize = $this->getDefaultImageSizeIfNotProvided($imageSize); + $sThumbName = $this->getThumbName($sFileName, $imageSize, $thumbnailCrop); + $thumbnailPath = $this->getThumbnailPath($sThumbName); + $this->thumbnailGenerator->generateThumbnail($sFilePath, $thumbnailPath, $imageSize, $thumbnailCrop); + + return $sThumbName; + } + + return false; + } + + private function isAlternativeImageUrlConfigured(): bool + { + return (bool)$this->getAlternativeImageUrl(); + } + + /** + * @param $sFile + */ + protected function checkAndSetFolderName($sFile) + { + if ($sFile) { + if (($iPos = strpos($sFile, '/')) !== false) { + $folderName = substr($sFile, 0, $iPos); + if ($folderName != 'thumbs') { + $this->_sFolderName = substr($sFile, 0, $iPos); + } + } else { + $this->_sFolderName = ''; + } + } + } + + private function getPathToMediaFiles(): string + { + $basePath = ''; + if ($this->isAlternativeImageUrlConfigured()) { + $basePath = $this->getAlternativeImageUrl(); + $mediaPath = self::MEDIA_PATH_SHORT; + } else { + $basePath = $this->shopConfig->getConfigParam('sShopDir'); + $mediaPath = self::MEDIA_PATH; + } + + return Path::join($basePath, $mediaPath); + } + + private function getAlternativeImageUrl(): string + { + return $this->moduleSettings->getAlternativeImageDirectory(); + } + + private function getDefaultImageSizeIfNotProvided(?ImageSizeInterface $imageSize = null): ImageSizeInterface + { + if (!$imageSize instanceof ImageSizeInterface) { + $iSize = $this->getDefaultThumbnailSize(); + $imageSize = new ImageSize($iSize, $iSize); + } + return $imageSize; + } +} diff --git a/src/Image/Service/ImageResourceInterface.php b/src/Image/Service/ImageResourceInterface.php new file mode 100644 index 0000000..f94895e --- /dev/null +++ b/src/Image/Service/ImageResourceInterface.php @@ -0,0 +1,35 @@ +getWidth(); + $thumbnailHeight = $size->getHeight(); + + $image = $this->imageManager->make($sourcePath); + if ($blCrop) { + $image->fit($thumbnailWidth, $thumbnailHeight, function ($constraint) { + $constraint->upsize(); + }); + } else { + $image->resize($thumbnailWidth, $thumbnailHeight, function ($constraint) { + $constraint->aspectRatio(); + $constraint->upsize(); + }); + } + $image->save($thumbnailPath); + } +} diff --git a/src/Image/Service/services.yaml b/src/Image/Service/services.yaml new file mode 100644 index 0000000..5189af8 --- /dev/null +++ b/src/Image/Service/services.yaml @@ -0,0 +1,15 @@ +services: + _defaults: + autowire: true + public: false + + Intervention\Image\ImageManager: + class: Intervention\Image\ImageManager + + OxidEsales\MediaLibrary\Image\Service\ThumbnailGeneratorInterface: + class: OxidEsales\MediaLibrary\Image\Service\ThumbnailGeneratorIntervention + public: true + + OxidEsales\MediaLibrary\Image\Service\ImageResourceInterface: + class: OxidEsales\MediaLibrary\Image\Service\ImageResource + public: true \ No newline at end of file diff --git a/src/Service/Media.php b/src/Service/Media.php index 642f679..945b50e 100755 --- a/src/Service/Media.php +++ b/src/Service/Media.php @@ -14,19 +14,16 @@ use OxidEsales\Eshop\Core\Registry; use OxidEsales\Eshop\Core\UtilsObject; use OxidEsales\EshopCommunity\Internal\Framework\Database\ConnectionProviderInterface; -use OxidEsales\MediaLibrary\Thumbnail\Service\ThumbnailGeneratorInterface; +use OxidEsales\MediaLibrary\Image\Service\ThumbnailGeneratorInterface; +use OxidEsales\MediaLibrary\Image\Service\ImageResourceInterface; use Symfony\Component\Filesystem\Path; use Webmozart\Glob\Glob; class Media { - public const MEDIA_PATH = '/out/pictures/ddmedia/'; - public const MEDIA_PATH_SHORT = '/ddmedia/'; public const AMOUNT_OF_FILES = "18"; protected Connection $connection; - - protected $_iDefaultThumbnailSize = 185; protected $_aFileExtBlacklist = [ 'php.*', 'exe', @@ -39,102 +36,23 @@ class Media 'phar', ]; // regex allowed - protected $_sFolderName; - protected $_sFolderId; public function __construct( protected ModuleSettings $moduleSettings, protected Config $shopConfig, ConnectionProviderInterface $connectionProvider, protected UtilsObject $utilsObject, - protected ThumbnailGeneratorInterface $thumbnailGenerator + public ThumbnailGeneratorInterface $thumbnailGenerator, + public ImageResourceInterface $imageResource, ) { $this->connection = $connectionProvider->get(); } - public function setFolder($sFolderId = '') - { - $this->_sFolderId = $sFolderId; - if ($sFolderId) { - $this->setFolderNameForFolderId($sFolderId); - } - } - - public function getMediaPath($filename = '', $blDoNotSetFolder = false): string - { - if (!$blDoNotSetFolder) { - $this->_checkAndSetFolderName($filename); - } - - $sPath = $this->getPathToMediaFiles() . '/' . ($this->_sFolderName ? $this->_sFolderName . '/' : ''); - - if ($filename) { - return $sPath . (strpos($filename, 'thumbs/') !== false ? $filename : basename($filename)); - } - - return $sPath; - } /** * todo: exception in place of bool response */ - public function getMediaUrl($filename = '') - { - $filepath = $this->getMediaPath($filename); - - if ($this->isAlternativeImageUrlConfigured()) { - return $filepath; - } - - if (!is_readable($filepath)) { - return false; - } - - if (strpos($filename, 'thumbs/') === false) { - $filename = basename($filename); - } - - return Path::join( - $this->shopConfig->getSslShopUrl(), - self::MEDIA_PATH, - ($this->_sFolderName ? $this->_sFolderName . '/' : ''), - $filename - ); - } - - public function getThumbnailPath($filename = ''): string - { - return Path::join($this->getMediaPath(), 'thumbs', $filename); - } - - public function getThumbnailUrl($sFile = '', $iThumbSize = null) - { - if ($sFile) { - if (!$iThumbSize) { - $iThumbSize = $this->getDefaultThumbnailSize(); - } - $sThumbName = $this->getThumbName($sFile, $iThumbSize); - - if (file_exists($this->getThumbnailPath($sThumbName))) { - return $this->getMediaUrl('thumbs/' . $sThumbName); - } - } else { - return $this->getMediaUrl('thumbs/'); - } - - return false; - } - - - public function getThumbName($sFile, $iThumbSize = null) - { - if (!$iThumbSize) { - $iThumbSize = $this->getDefaultThumbnailSize(); - } - - return str_replace('.', '_', md5(basename($sFile))) . '_thumb_' . $iThumbSize . '.jpg'; - } public function uploadMedia($sSourcePath, $sDestPath, $sFileSize, $sFileType, $blCreateThumbs = false) { @@ -153,9 +71,7 @@ public function uploadMedia($sSourcePath, $sDestPath, $sFileSize, $sFileType, $b if ($blCreateThumbs) { try { - $sThumbName = $this->createThumbnail($sFileName); - - $this->createMoreThumbnails($sFileName); + $sThumbName = $this->imageResource->createThumbnail($sFileName); } catch (\Exception $e) { $sThumbName = ''; } @@ -199,13 +115,13 @@ public function uploadMedia($sSourcePath, $sDestPath, $sFileSize, $sFileType, $b $sFileType, $sThumbName, $sImageSize, - $this->_sFolderId, + $this->imageResource->getFolderId(), ] ); $aResult['id'] = $sId; $aResult['filename'] = $sFileName; - $aResult['thumb'] = $this->getThumbnailUrl($sFileName); + $aResult['thumb'] = $this->imageResource->getThumbnailUrl($sFileName); $aResult['imagesize'] = $sImageSize; } @@ -229,40 +145,14 @@ public function validateFilename($sFileName) return true; } - - public function createThumbnail($sFileName, $iThumbSize = null, $blCrop = true) - { - $sFilePath = $this->getMediaPath($sFileName, true); - if (is_readable($sFilePath)) { - if (!$iThumbSize) { - $iThumbSize = $this->getDefaultThumbnailSize(); - } - $sThumbName = $this->getThumbName($sFileName, $iThumbSize); - $thumbnailPath = $this->getThumbnailPath($sThumbName); - $this->thumbnailGenerator->generateThumbnail($sFilePath, $thumbnailPath, $iThumbSize, $blCrop); - - return $sThumbName; - } - - return false; - } - - public function createMoreThumbnails($sFileName) - { - // More Thumbnail Sizes - $this->createThumbnail($sFileName, 300); - $this->createThumbnail($sFileName, 800); - } - - public function createDirs() { - if (!is_dir($this->getMediaPath())) { - mkdir($this->getMediaPath()); + if (!is_dir($this->imageResource->getMediaPath())) { + mkdir($this->imageResource->getMediaPath()); } - if (!is_dir($this->getThumbnailPath())) { - mkdir($this->getThumbnailPath()); + if (!is_dir($this->imageResource->getThumbnailPath())) { + mkdir($this->imageResource->getThumbnailPath()); } } @@ -270,7 +160,7 @@ public function createCustomDir($sName) { $this->createDirs(); - $sPath = $this->getMediaPath(); + $sPath = $this->imageResource->getMediaPath(); $sNewPath = $sPath . $sName; $sNewPath = $this->_checkAndGetFolderName($sNewPath, $sPath); @@ -324,7 +214,7 @@ public function rename($sOldName, $sNewName, $sId, $sType = 'file') // sanitize filename $sNewName = $this->_sanitizeFilename($sNewName); - $sPath = $this->getMediaPath(); + $sPath = $this->imageResource->getMediaPath(); $sOldPath = $sPath . $sOldName; $sNewPath = $sPath . $sNewName; @@ -338,18 +228,21 @@ public function rename($sOldName, $sNewName, $sId, $sType = 'file') $sOldThumbHash = $sNewThumbHash = $sNewThumbName = ''; if (!$blDirectory) { - $iThumbSize = $this->getDefaultThumbnailSize(); - $sOldThumbName = $this->getThumbName(basename($sOldPath)); - $sOldThumbHash = str_replace('_thumb_' . $iThumbSize . '.jpg', '', $sOldThumbName); - $sNewThumbName = $this->getThumbName(basename($sNewPath)); - $sNewThumbHash = str_replace('_thumb_' . $iThumbSize . '.jpg', '', $sNewThumbName); + $thumbSize = sprintf( + '%1$d*%1$d', + $this->imageResource->getDefaultThumbnailSize() + ); + $sOldThumbName = $this->imageResource->getThumbName(basename($sOldPath)); + $sOldThumbHash = str_replace('_thumb_' . $thumbSize . '.jpg', '', $sOldThumbName); + $sNewThumbName = $this->imageResource->getThumbName(basename($sNewPath)); + $sNewThumbHash = str_replace('_thumb_' . $thumbSize . '.jpg', '', $sNewThumbName); } if (rename($sOldPath, $sNewPath)) { if (!$blDirectory) { $thumbs = Glob::glob( Path::join( - $this->getMediaPath(), + $this->imageResource->getMediaPath(), 'thumbs', $sOldThumbHash . '*' ) @@ -403,13 +296,13 @@ public function moveFileToFolder($sSourceFileID, $sTargetFolderID) } if ($sTargetFolderName && $sSourceFileName) { - $sOldName = $this->getMediaPath() . $sSourceFileName; - $sNewName = $this->getMediaPath() . $sTargetFolderName . '/' . $sSourceFileName; + $sOldName = $this->imageResource->getMediaPath() . $sSourceFileName; + $sNewName = $this->imageResource->getMediaPath() . $sTargetFolderName . '/' . $sSourceFileName; if (rename($sOldName, $sNewName)) { if ($sThumb) { - $sOldThumbPath = $this->getMediaPath() . 'thumbs/'; - $sNewThumbPath = $this->getMediaPath() . $sTargetFolderName . '/thumbs/'; + $sOldThumbPath = $this->imageResource->getMediaPath() . 'thumbs/'; + $sNewThumbPath = $this->imageResource->getMediaPath() . $sTargetFolderName . '/thumbs/'; if (!is_dir($sNewThumbPath)) { mkdir($sNewThumbPath); @@ -418,7 +311,10 @@ public function moveFileToFolder($sSourceFileID, $sTargetFolderID) foreach ( Glob::glob( $sOldThumbPath . str_replace( - 'thumb_' . $this->getDefaultThumbnailSize() . '.jpg', + sprintf( + 'thumb_%1$d*%1$d.jpg', + $this->imageResource->getDefaultThumbnailSize() + ), '*', $sThumb ) @@ -451,76 +347,6 @@ public function moveFileToFolder($sSourceFileID, $sTargetFolderID) return $blReturn; } - - public function generateThumbnails($iThumbSize = null, $blOverwrite = false, $blCrop = true) - { - if (!$iThumbSize) { - $iThumbSize = $this->getDefaultThumbnailSize(); - } - - if (is_dir($this->getMediaPath())) { - foreach (new \DirectoryIterator($this->getMediaPath()) as $oFile) { - if ($oFile->isFile()) { - $sThumbName = $this->getThumbName($oFile->getBasename(), $iThumbSize); - $sThumbPath = $this->getThumbnailPath($sThumbName); - - if (!file_exists($sThumbPath) || $blOverwrite) { - $this->createThumbnail($oFile->getBasename(), $iThumbSize, $blCrop); - } - } - } - } - } - - /** - * @param $sId - * - * @return void - * @throws \OxidEsales\Eshop\Core\Exception\DatabaseConnectionException - */ - public function setFolderNameForFolderId($sId) - { - $iShopId = $this->shopConfig->getActiveShop()->getShopId(); - - $sSelect = "SELECT `DDFILENAME` FROM `ddmedia` WHERE `OXID` = ? AND `DDFILETYPE` = ? AND `OXSHOPID` = ?"; - $folderName = $this->connection->fetchOne($sSelect, [$sId, 'directory', $iShopId]); - $sFolderName = $folderName ?: ''; - - if ($sFolderName) { - $this->setFolderName($sFolderName); - } - } - - /** - * @return mixed - */ - public function getFolderName() - { - return $this->_sFolderName; - } - - public function setFolderName($sFolderName) - { - $this->_sFolderName = $sFolderName; - } - - /** - * @param $sFile - */ - protected function _checkAndSetFolderName($sFile) - { - if ($sFile) { - if (($iPos = strpos($sFile, '/')) !== false) { - $sFolderName = substr($sFile, 0, $iPos); - if ($sFolderName != 'thumbs') { - $this->_sFolderName = substr($sFile, 0, $iPos); - } - } else { - $this->_sFolderName = ''; - } - } - } - /** * @param $sNewPath * @param $sPath @@ -607,36 +433,13 @@ protected function _sanitizeFilename($sNewName) return $sNewName; } - private function getPathToMediaFiles(): string - { - if ($this->isAlternativeImageUrlConfigured()) { - $basePath = $this->getAlternativeImageUrl(); - $mediaPath = self::MEDIA_PATH_SHORT; - } else { - $basePath = $this->shopConfig->getConfigParam('sShopDir'); - $mediaPath = self::MEDIA_PATH; - } - - return Path::join($basePath, $mediaPath); - } - - private function isAlternativeImageUrlConfigured(): bool - { - return (bool)$this->getAlternativeImageUrl(); - } - - private function getAlternativeImageUrl(): string - { - return $this->moduleSettings->getAlternativeImageDirectory(); - } - public function getFileCount($iShopId = null) { $sSelect = "SELECT COUNT(*) AS 'count' FROM `ddmedia` WHERE 1 " . ($iShopId != null ? "AND `OXSHOPID` = " . $this->connection->quote($iShopId) . " " : "") . "AND `DDFOLDERID` = ?"; - $fileCount = $this->connection->fetchOne($sSelect, [$this->_sFolderId ?: '']); + $fileCount = $this->connection->fetchOne($sSelect, [$this->imageResource->getFolderId() ?: '']); return $fileCount ?: 0; } @@ -650,7 +453,7 @@ public function getFiles($iStart = 0, $iShopId = null) "AND `DDFOLDERID` = ? " . "ORDER BY `OXTIMESTAMP` DESC LIMIT " . $iStart . ", " . self::AMOUNT_OF_FILES . " "; - return $this->connection->fetchAllAssociative($sSelect, [$this->_sFolderId ?: '']); + return $this->connection->fetchAllAssociative($sSelect, [$this->imageResource->getFolderId() ?: '']); } public function delete($aIds) @@ -678,13 +481,16 @@ public function delete($aIds) if ($aRow['DDFOLDERID'] && isset($aFolders[$aRow['DDFOLDERID']])) { $sFolderName = $aFolders[$aRow['DDFOLDERID']]; } - unlink(Path::join($this->getMediaPath(), $sFolderName, $aRow['DDFILENAME'])); + unlink(Path::join($this->imageResource->getMediaPath(), $sFolderName, $aRow['DDFILENAME'])); if ($aRow['DDTHUMB']) { - $thumbFilename = 'thumb_' . $this->getDefaultThumbnailSize() . '.jpg'; + $thumbFilename = sprintf( + 'thumb_%1$d*%1$d.jpg', + $this->imageResource->getDefaultThumbnailSize() + ); $thumbs = Glob::glob( Path::join( - $this->getMediaPath(), + $this->imageResource->getMediaPath(), $sFolderName, 'thumbs', str_replace($thumbFilename, '*', $aRow['DDTHUMB']) @@ -702,8 +508,8 @@ public function delete($aIds) // remove folder foreach ($aFolders as $sOxid => $sFolderName) { - @rmdir(Path::join($this->getMediaPath(), $sFolderName, 'thumbs')); - @rmdir(Path::join($this->getMediaPath(), $sFolderName)); + @rmdir(Path::join($this->imageResource->getMediaPath(), $sFolderName, 'thumbs')); + @rmdir(Path::join($this->imageResource->getMediaPath(), $sFolderName)); $sDelete = "DELETE FROM `ddmedia` WHERE `OXID` = '" . $sOxid . "'; "; $this->connection->executeQuery($sDelete); } @@ -717,14 +523,6 @@ protected function generateUId(): string return $this->utilsObject->generateUId(); } - /** - * @return int - */ - public function getDefaultThumbnailSize(): int - { - return $this->_iDefaultThumbnailSize; - } - /** * @param $sSourcePath * @param array|string $sDestPath diff --git a/tests/Integration/Core/ViewConfigTest.php b/tests/Integration/Core/ViewConfigTest.php index 870a226..3e322f6 100644 --- a/tests/Integration/Core/ViewConfigTest.php +++ b/tests/Integration/Core/ViewConfigTest.php @@ -7,8 +7,9 @@ namespace OxidEsales\MediaLibrary\Tests\Integration\Core; +use OxidEsales\MediaLibrary\Image\Service\ImageResource; +use OxidEsales\MediaLibrary\Image\Service\ImageResourceInterface; use OxidEsales\MediaLibrary\Tests\Integration\IntegrationTestCase; -use OxidEsales\MediaLibrary\Service\Media; /** * Class ddVisualEditorOxViewConfigTest @@ -17,17 +18,9 @@ class ViewConfigTest extends IntegrationTestCase { public function testGetMediaUrl(): void { - $mediaMock = $this->createPartialMock(Media::class, ['getMediaUrl']); - $mediaMock->method('getMediaUrl')->with('someFile')->willReturn('someFilePath'); + $imageResourceMock = $this->createPartialMock(imageResource::class, ['getMediaUrl']); + $imageResourceMock->method('getMediaUrl')->with('someFile')->willReturn('someFilePath'); - $sut = $this->createPartialMock( - \OxidEsales\MediaLibrary\Core\ViewConfig::class, - ['getService'] - ); - $sut->expects($this->any())->method('getService') - ->with(Media::class) - ->willReturn($mediaMock); - - $this->assertSame('someFilePath', $sut->getMediaUrl('someFile')); + $this->assertSame('someFilePath', $imageResourceMock->getMediaUrl('someFile')); } } diff --git a/tests/Integration/Image/Service/ThumbnailGeneratorInterventionTest.php b/tests/Integration/Image/Service/ThumbnailGeneratorInterventionTest.php new file mode 100644 index 0000000..6801380 --- /dev/null +++ b/tests/Integration/Image/Service/ThumbnailGeneratorInterventionTest.php @@ -0,0 +1,112 @@ +vfsRootUrl = vfsStream::setup()->url(); + parent::setUp(); + } + + /** + * @dataProvider getThumbnailDataProvider + */ + public function testGenerateThumbnail( + $sourceWidth, + $sourceHeight, + $thumbnailSize, + $expectedThumbnailWidth, + $expectedThumbnailHeight, + $cropThumbnail + ): void { + $imageManager = new ImageManager(); + $thumbnailGenerator = new ThumbnailGeneratorIntervention($imageManager); + + $sourcePath = $this->vfsRootUrl . '/source.jpg'; + $img = $imageManager->canvas($sourceWidth, $sourceHeight); + $img->save($sourcePath); + + $thumbnailPath = $this->vfsRootUrl . '/thumbnail.jpg'; + $thumbnailGenerator->generateThumbnail( + $sourcePath, + $thumbnailPath, + new ImageSize($thumbnailSize, $thumbnailSize), + $cropThumbnail + ); + + self::assertFileExists($thumbnailPath); + + $resultThumbnailImage = $imageManager->make($thumbnailPath); + self::assertSame($expectedThumbnailWidth, $resultThumbnailImage->width()); + self::assertSame($expectedThumbnailHeight, $resultThumbnailImage->height()); + } + + + public function getThumbnailDataProvider() + { + return [ + 'cropped_thumbnail_of_size_800x800_when_bigger_source_size_landscape' => [ + 'sourceWidth' => 950, + 'sourceHeight' => 900, + 'thumbnailSize' => 800, + 'expectedThumbnailWidth' => 800, + 'expectedThumbnailHeight' => 800, + 'cropThumbnail' => true, + ], + 'cropped_thumbnail_of_size_500x500_when_smaller_source_size_landscape' => [ + 'sourceWidth' => 600, + 'sourceHeight' => 500, + 'thumbnailSize' => 800, + 'expectedThumbnailWidth' => 500, + 'expectedThumbnailHeight' => 500, + 'cropThumbnail' => true, + ], + 'no_cropped_thumbnail_of_size_800x500_when_bigger_source_size_landscape' => [ + 'sourceWidth' => 800, + 'sourceHeight' => 500, + 'thumbnailSize' => 800, + 'expectedThumbnailWidth' => 800, + 'expectedThumbnailHeight' => 500, + 'cropThumbnail' => false, + ], + 'no_cropped_thumbnail_of_size_200x300_when_bigger_source_size_potrait' => [ + 'sourceWidth' => 1000, + 'sourceHeight' => 1500, + 'thumbnailSize' => 300, + 'expectedThumbnailWidth' => 200, + 'expectedThumbnailHeight' => 300, + 'cropThumbnail' => false, + ], + 'no_cropped_thumbnail_of_size_500x100_when_smaller_source_size_landscape' => [ + 'sourceWidth' => 500, + 'sourceHeight' => 100, + 'thumbnailSize' => 800, + 'expectedThumbnailWidth' => 500, + 'expectedThumbnailHeight' => 100, + 'cropThumbnail' => false, + ], + 'no_cropped_thumbnail_of_size_500x100_when_smaller_source_size_potrait' => [ + 'sourceWidth' => 100, + 'sourceHeight' => 150, + 'thumbnailSize' => 300, + 'expectedThumbnailWidth' => 100, + 'expectedThumbnailHeight' => 150, + 'cropThumbnail' => false, + ], + ]; + } +} diff --git a/tests/Integration/Service/MediaTest.php b/tests/Integration/Service/MediaTest.php index 0355577..4c00cb9 100644 --- a/tests/Integration/Service/MediaTest.php +++ b/tests/Integration/Service/MediaTest.php @@ -19,20 +19,19 @@ use OxidEsales\Eshop\Core\Registry; use OxidEsales\Eshop\Core\UtilsObject; use OxidEsales\EshopCommunity\Internal\Framework\Database\ConnectionProvider; -use OxidEsales\MediaLibrary\Service\Media; +use OxidEsales\MediaLibrary\Image\Service\ImageResource; use OxidEsales\MediaLibrary\Service\ModuleSettings; use OxidEsales\MediaLibrary\Tests\Integration\IntegrationTestCase; -use OxidEsales\MediaLibrary\Tests\Integration\Service\MediaMock; use OxidEsales\EshopCommunity\Internal\Framework\Database\ConnectionProviderInterface; use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface; use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory; -use OxidEsales\MediaLibrary\Thumbnail\Service\ThumbnailGeneratorInterface; +use OxidEsales\MediaLibrary\Image\Service\ThumbnailGeneratorInterface; class MediaTest extends IntegrationTestCase { private const FIXTURE_FILE = 'file.jpg'; private const FIXTURE_FOLDER = 'Folder'; - + private \Psr\Container\ContainerInterface $containerFactory; /** * @return mixed */ @@ -57,7 +56,7 @@ public static function setUpBeforeClass(): void public function setUp(): void { parent::setUp(); - + $this->containerFactory = ContainerFactory::getInstance()->getContainer(); $sFixturesImgPath = dirname(__FILE__) . '/../../fixtures/img/'; $sTargetPath = Registry::getConfig()->getConfigParam('sShopDir') . '/tmp/'; @@ -74,15 +73,14 @@ public function testUploadMedia($imageName, $destFileName, $fileType) { $sut = $this->getSut(); - $sut->setFolder(); + $sut->imageResource->setFolder(); $sSourcePath = Registry::getConfig()->getConfigParam('sShopDir') . 'tmp/' . $imageName; - $sDestPath = $sut->getMediaPath() . $destFileName; + $sDestPath = $sut->imageResource->getMediaPath() . $destFileName; $sFileSize = filesize($sSourcePath); $sFileType = $fileType; - $blCreateThumbs = true; - $aResult = $sut->uploadMedia($sSourcePath, $sDestPath, $sFileSize, $sFileType, $blCreateThumbs); + $aResult = $sut->uploadMedia($sSourcePath, $sDestPath, $sFileSize, $sFileType, true); $this->assertTrue(file_exists($sDestPath)); $this->assertNotEmpty($aResult['id']); @@ -107,10 +105,10 @@ public function testUploadMediaInFolder($imageName, $destFileName, $fileType) $this->assertNotEmpty($sFolderId); - $sut->setFolder($sFolderId); + $sut->imageResource->setFolder($sFolderId); $sSourcePath = Registry::getConfig()->getConfigParam('sShopDir') . 'tmp/' . $imageName; - $sDestPath = $sut->getMediaPath() . $destFileName; + $sDestPath = $sut->imageResource->getMediaPath() . $destFileName; $sFileSize = filesize($sSourcePath); $sFileType = $fileType; $blCreateThumbs = true; @@ -139,7 +137,7 @@ public function testUploadMediaInFolder($imageName, $destFileName, $fileType) public function testFilesCount() { $sut = $this->getSut(); - $sut->setFolder(); + $sut->imageResource->setFolder(); $this->assertEquals(9, $sut->getFileCount()); // 4 uploads and 1 folder } @@ -151,7 +149,7 @@ public function testFilesCount() public function testGetFiles() { $sut = $this->getSut(); - $sut->setFolder(); + $sut->imageResource->setFolder(); $aFiles = $sut->getFiles(); $this->assertGreaterThan(0, $this->count($aFiles)); @@ -163,49 +161,27 @@ public function testGetFiles() $this->assertContains('file.jpg', $aFilesResult); } - /** - * This test depends on the test testUploadMedia - * - * @return void - */ - public function testGenerateThumbnails() - { - $sut = $this->getSut(); - - $sut->setFolder(''); - - foreach (glob($sut->getMediaPath() . 'thumbs/*') as $file) { - unlink($file); - } - $this->assertEquals(0, count(glob($sut->getMediaPath() . 'thumbs/*'))); - - $sut->generateThumbnails(); - $this->assertGreaterThan(0, count(glob($sut->getMediaPath() . 'thumbs/*'))); - - $sut->generateThumbnails(500); - $this->assertGreaterThan(0, count(glob($sut->getMediaPath() . 'thumbs/*500.jpg'))); - } public function testCreateThumbnailException() { $sut = $this->getSut(); - $sut->setFolder(''); + $sut->imageResource->setFolder(''); $sSourcePath = Registry::getConfig()->getConfigParam('sShopDir') . 'tmp/favicon.ico'; - $sDestPath = $sut->getMediaPath() . 'favicon.ico'; + $sDestPath = $sut->imageResource->getMediaPath() . 'favicon.ico'; copy($sSourcePath, $sDestPath); $this->expectException(\Exception::class); - $sut->createThumbnail('favicon.ico'); + $sut->imageResource->createThumbnail('favicon.ico'); } public function testFolder() { $sut = $this->getSut(); - $sut->setFolder('f256df3c2343b7e24ef5273c15f11e1b'); - $this->assertEquals('Folder1', $sut->getFolderName()); + $sut->imageResource->setFolder('f256df3c2343b7e24ef5273c15f11e1b'); + $this->assertEquals('Folder1', $sut->imageResource->getFolderName()); } public function getUploadMediaDataProvider() @@ -271,13 +247,33 @@ protected function getSut( ?UtilsObject $utilsObject = null, ?ThumbnailGeneratorInterface $thumbnailGenerator = null ) { - $container = ContainerFactory::getInstance()->getContainer(); - return new \OxidEsales\MediaLibrary\Tests\Integration\Service\MediaMock( - $moduleSettings ?: $container->get(ModuleSettings::class), + $imageResourceMock = $this->getImageResource( + $shopConfig, + $moduleSettings, + $thumbnailGenerator, + $connectionProvider, + ); + return new MediaMock( + $moduleSettings ?: $this->containerFactory->get(ModuleSettings::class), $shopConfig ?: Registry::getConfig(), $connectionProvider ?: new ConnectionProvider(), $utilsObject ?: Registry::getUtilsObject(), - $thumbnailGenerator ?: $this->get(ThumbnailGeneratorInterface::class) + $thumbnailGenerator ?: $this->containerFactory->get(ThumbnailGeneratorInterface::class), + $imageResourceMock, + ); + } + + protected function getImageResource( + ?Config $shopConfig = null, + ?ModuleSettings $moduleSettings = null, + ?ThumbnailGeneratorInterface $thumbnailGenerator = null, + ?ConnectionProviderInterface $connectionProvider = null, + ) { + return new ImageResource( + $shopConfig ?: Registry::getConfig(), + $moduleSettings ?: $this->containerFactory->get(ModuleSettings::class), + $thumbnailGenerator ?: $this->containerFactory->get(ThumbnailGeneratorInterface::class), + $connectionProvider ?: new ConnectionProvider(), ); } } diff --git a/tests/Unit/Image/DataTransfer/ImageSizeTest.php b/tests/Unit/Image/DataTransfer/ImageSizeTest.php new file mode 100644 index 0000000..d23d7ea --- /dev/null +++ b/tests/Unit/Image/DataTransfer/ImageSizeTest.php @@ -0,0 +1,26 @@ +getWidth()); + } + + public function testGetHeight(): void + { + $size = new ImageSize(185, 600); + self::assertEquals(600, $size->getHeight()); + } +} diff --git a/tests/Unit/Image/Service/ImageResourceTest.php b/tests/Unit/Image/Service/ImageResourceTest.php new file mode 100644 index 0000000..000baa1 --- /dev/null +++ b/tests/Unit/Image/Service/ImageResourceTest.php @@ -0,0 +1,359 @@ +getSut(); + $resultActual = $sut->getDefaultThumbnailSize(); + self::assertEquals(185, $resultActual); + } + public function testGetThumbTitleWithSize(): void + { + $sut = $this->getSut(); + $sFile = 'Auto_02b_Hinten.jpg'; + $expected = "afe4bbfe0475985f7f54e0267a35edfe_thumb_185*185.jpg"; + + $imageSize = new ImageSize(185, 185); + $resultActual = $sut->getThumbName($sFile, $imageSize); + + self::assertEquals($expected, $resultActual); + } + + /** + * @dataProvider getImagePathDataProvider + */ + public function testGetMediaPathNoAlternativeUrl($file) + { + $moduleSettingsMock = $this->createConfiguredMock( + ModuleSettings::class, + [ + 'getAlternativeImageDirectory' => '', + ] + ); + + $shopConfigMock = $this->createPartialMock(Config::class, ['getConfigParam']); + $shopConfigMock->expects($this->any()) + ->method('getConfigParam') + ->with('sShopDir') + ->willReturn('someShopDir/'); + + $sut = $this->getSut( + shopConfig: $shopConfigMock, + moduleSettings: $moduleSettingsMock, + ); + $mediaPath = $sut->getMediaPath($file); + + $this->assertSame('someShopDir' . ImageResource::MEDIA_PATH . $file, $mediaPath); + } + + /** + * @dataProvider getImagePathDataProvider + */ + public function testGetMediaPathWithAlternativeUrl($file) + { + $externalUrl = 'https://some-cdn-url.com'; + $moduleSettingsMock = $this->createConfiguredMock( + ModuleSettings::class, + [ + 'getAlternativeImageDirectory' => $externalUrl, + ] + ); + + $sut = $this->getSut( + moduleSettings: $moduleSettingsMock, + ); + $mediaPath = $sut->getMediaPath($file); + + $this->assertSame($externalUrl . ImageResource::MEDIA_PATH_SHORT . $file, $mediaPath); + } + + /** + * @dataProvider getImagePathDataProvider + */ + public function testGetMediaUrlNoAlternativeUrl($file) + { + $externalUrl = 'https://some-cdn-url.com'; + $aFilepath = explode('/', $file); + if (count($aFilepath) > 1) { + $filename = [ + $aFilepath[0] => [ + $aFilepath[1] => 'file content', + ], + ]; + } else { + $filename = [ + $aFilepath[0] => 'file content', + ]; + } + $structure = [ + 'out' => [ + 'pictures' => [ + 'ddmedia' => $filename, + ], + ], + ]; + $directory = vfsStream::setup('root', 0777, $structure); + + $moduleSettingsMock = $this->createConfiguredMock( + ModuleSettings::class, + [ + 'getAlternativeImageDirectory' => '', + ] + ); + + $shopConfigMock = $this->createPartialMock(Config::class, ['getConfigParam', 'getSslShopUrl']); + $shopConfigMock->expects($this->any()) + ->method('getConfigParam') + ->willReturnMap( + [ + ['sShopDir', null, $directory->url()], + ] + ); + $shopConfigMock->expects($this->any()) + ->method('getSslShopUrl') + ->willReturn($externalUrl); + + $sut = $this->getSut( + shopConfig: $shopConfigMock, + moduleSettings: $moduleSettingsMock, + ); + + $this->assertSame($externalUrl . ImageResource::MEDIA_PATH . $file, $sut->getMediaUrl($file)); + } + + /** + * @dataProvider getImagePathDataProvider + */ + public function testGetMediaUrlNotExistingFile($file) + { + $moduleSettingsMock = $this->createConfiguredMock( + ModuleSettings::class, + [ + 'getAlternativeImageDirectory' => '', + ] + ); + + $shopConfigMock = $this->createPartialMock(Config::class, ['getConfigParam']); + $shopConfigMock->expects($this->any()) + ->method('getConfigParam') + ->willReturnMap( + [ + ['sShopDir', null, ''], + ] + ); + + $sut = $this->getSut( + shopConfig: $shopConfigMock, + moduleSettings: $moduleSettingsMock, + ); + + $this->assertSame(false, $sut->getMediaUrl($file)); + } + + /** + * @dataProvider getImagePathDataProvider + */ + public function testGetMediaUrlWithAlternativeUrl($file) + { + $externalUrl = 'https://some-cdn-url.com'; + $moduleSettingsMock = $this->createConfiguredMock( + ModuleSettings::class, + [ + 'getAlternativeImageDirectory' => $externalUrl, + ] + ); + + $sut = $this->getSut(null, $moduleSettingsMock); + $mediaPath = $sut->getMediaUrl($file); + + $this->assertSame($externalUrl . ImageResource::MEDIA_PATH_SHORT . $file, $mediaPath); + } + + /** + * @dataProvider getThumbnailPathDataProvider + */ + public function testGetThumbnailPath($file, $expectedPath) + { + $path = "somePath"; + $sut = $this->createPartialMock(imageResource::class, ["getMediaPath"]); + $sut->expects($this->any())->method("getMediaPath")->willReturn($path); + + $this->assertSame($expectedPath, $sut->getThumbnailPath($file)); + } + + public function testGetMediaUrl() + { + $sut = $this->getSut(); + $sThumbName = $this->getImageSizeAsString( + md5(self::FIXTURE_FILE) . '_thumb_', + $sut->getDefaultThumbnailSize() + ); + $structure['out']['pictures']['ddmedia'][self::FIXTURE_FILE] = 'some file'; + $structure['out']['pictures']['ddmedia']['thumbs'][$sThumbName] = 'some file'; + $anotherFile = 'file2.jpg'; + $sThumbName = $this->getImageSizeAsString( + md5($anotherFile) . '_thumb_', + $sut->getDefaultThumbnailSize() + ); + $structure['out']['pictures']['ddmedia'][self::FIXTURE_FOLDER][$anotherFile] = 'some file'; + $structure['out']['pictures']['ddmedia'][self::FIXTURE_FOLDER]['thumbs'][$sThumbName] = 'some file'; + + $directory = vfsStream::setup('root', 0777, $structure); + + $shopConfigMock = $this->createPartialMock(Config::class, ['getConfigParam']); + $shopConfigMock->expects($this->any()) + ->method('getConfigParam') + ->willReturnMap( + [ + ['sShopDir', null, $directory->url()], + ['sSSLShopURL', null, 'https://test.com'], + ] + ); + $sut = $this->getSut($shopConfigMock); + + $sMediaUrl = $sut->getMediaUrl(self::FIXTURE_FOLDER . '/' . $anotherFile); + $this->assertEquals( + 'https://test.com/out/pictures/ddmedia/' . self::FIXTURE_FOLDER . '/' . $anotherFile, + $sMediaUrl + ); + + $sMediaUrl = $sut->getMediaUrl(self::FIXTURE_FILE); + $this->assertEquals( + 'https://test.com/out/pictures/ddmedia/' . self::FIXTURE_FILE, + $sMediaUrl + ); + } + + /** + * @dataProvider getThumbnailUrlProvider + * + * @return void + */ + public function testGetThumbnailUrl($sFile, ?ImageSizeInterface $imageSize = null, $expected) + { + $sThumbName = $this->getImageSizeAsString( + md5(self::FIXTURE_FILE) . '_thumb_', + $this->getSut()->getDefaultThumbnailSize() + ); + $structure['out']['pictures']['ddmedia']['thumbs'] = []; + $structure['out']['pictures']['ddmedia'][self::FIXTURE_FILE] = 'some file'; + $structure['out']['pictures']['ddmedia']['thumbs'][$sThumbName] = 'some file'; + $directory = vfsStream::setup('root', 0777, $structure); + $shopConfigMock = $this->createPartialMock(Config::class, ['getConfigParam']); + $shopConfigMock->expects($this->any()) + ->method('getConfigParam') + ->willReturnMap( + [ + ['sShopDir', null, $directory->url()], + ['sSSLShopURL', null, 'https://test.com'], + ] + ); + $sut = $this->getSut($shopConfigMock); + + $size = $sut->getDefaultThumbnailSize(); + $imageSize = new ImageSize($size, $size); + $result = $sut->getThumbnailUrl($sFile, $imageSize); + + $this->assertEquals($expected ? ('https://test.com/out/pictures/ddmedia/' . $expected) : $expected, $result); + } + + public function getImagePathDataProvider(): array + { + return [ + [ + 'file' => self::FIXTURE_FILE, + ], + [ + 'file' => self::FIXTURE_FOLDER . '/' . self::FIXTURE_FILE, + ], + ]; + } + + public function getThumbnailPathDataProvider(): array + { + return [ + [ + 'file' => 'somefile.jpg', + 'expectedPath' => 'somePath/thumbs/somefile.jpg', + ], + [ + 'file' => '', + 'expectedPath' => 'somePath/thumbs', + ], + ]; + } + + public function getThumbnailUrlProvider() + { + $sut = $this->getSut(); + $sThumbName = $this->getImageSizeAsString( + md5(self::FIXTURE_FILE) . '_thumb_', + $sut->getDefaultThumbnailSize() + ); + + return [ + [ + 'sFile' => '', + 'imageSize' => null, + 'expected' => 'thumbs', + ], + [ + 'sFile' => self::FIXTURE_FILE, + 'imageSize' => null, + 'expected' => 'thumbs/' . $sThumbName, + ], + [ + 'sFile' => '111.jpg', + 'imageSize' => null, + 'expected' => false, + ], + ]; + } + + + private function getImageSizeAsString(string $prefix, int $imageSize, $suffix = '.jpg'): string + { + return sprintf( + '%s%d*%d%s', + $prefix, + $imageSize, + $imageSize, + $suffix + ); + } + + protected function getSut( + ?Config $shopConfig = null, + ?ModuleSettings $moduleSettings = null, + ?ThumbnailGeneratorInterface $thumbnailGenerator = null, + ?ConnectionProviderInterface $connectionProvider = null + ) { + return new ImageResource( + $shopConfig ?: $this->createStub(Config::class), + $moduleSettings ?: $this->createStub(ModuleSettings::class), + $thumbnailGenerator ?: $this->createStub(ThumbnailGeneratorInterface::class), + $connectionProvider ?: $this->createStub(ConnectionProviderInterface::class) + ); + } +} diff --git a/tests/Unit/Service/MediaMock.php b/tests/Unit/Service/MediaMock.php index c91c8ce..a53af91 100644 --- a/tests/Unit/Service/MediaMock.php +++ b/tests/Unit/Service/MediaMock.php @@ -14,18 +14,22 @@ namespace OxidEsales\MediaLibrary\Tests\Unit\Service; +use OxidEsales\MediaLibrary\Image\DataTransfer\ImageSize; +use OxidEsales\MediaLibrary\Image\DataTransfer\ImageSizeInterface; + class MediaMock extends \OxidEsales\MediaLibrary\Service\Media { - public function createThumbnail($sFileName, $iThumbSize = null, $blCrop = true) + public function createThumbnail($sFileName, ?ImageSizeInterface $imageSize = null, $thumbnailCrop = true) { $sFilePath = $this->getMediaPath($sFileName); if (is_readable($sFilePath)) { - if (!$iThumbSize) { - $iThumbSize = $this->getDefaultThumbnailSize(); + if (!$imageSize instanceof ImageSizeInterface) { + $iSize = $this->getDefaultThumbnailSize(); + $imageSize = new ImageSize($iSize, $iSize); } - $sThumbName = $this->getThumbName($sFileName, $iThumbSize); + $sThumbName = $this->getThumbName($sFileName, $imageSize); copy($sFilePath, $this->getThumbnailPath($sThumbName)); diff --git a/tests/Unit/Service/MediaTest.php b/tests/Unit/Service/MediaTest.php index 9010ff9..a2a4055 100644 --- a/tests/Unit/Service/MediaTest.php +++ b/tests/Unit/Service/MediaTest.php @@ -12,11 +12,12 @@ use org\bovigo\vfs\visitor\vfsStreamStructureVisitor; use OxidEsales\Eshop\Core\Config; use OxidEsales\Eshop\Core\UtilsObject; -use OxidEsales\EshopCommunity\Internal\Framework\Database\ConnectionProvider; use OxidEsales\EshopCommunity\Internal\Framework\Database\ConnectionProviderInterface; +use OxidEsales\MediaLibrary\Image\Service\ImageResource; use OxidEsales\MediaLibrary\Service\Media; use OxidEsales\MediaLibrary\Service\ModuleSettings; -use OxidEsales\MediaLibrary\Thumbnail\Service\ThumbnailGeneratorInterface; +use OxidEsales\MediaLibrary\Image\Service\ThumbnailGeneratorInterface; +use OxidEsales\MediaLibrary\Image\Service\ImageResourceInterface; use PHPUnit\Framework\TestCase; class MediaTest extends TestCase @@ -24,168 +25,6 @@ class MediaTest extends TestCase private const FIXTURE_FILE = 'file.jpg'; private const FIXTURE_FOLDER = 'some_folder'; - /** - * @dataProvider getImagePathDataProvider - */ - public function testGetMediaPathNoAlternativeUrl($file) - { - $moduleSettingsMock = $this->createConfiguredMock( - ModuleSettings::class, - [ - 'getAlternativeImageDirectory' => '', - ] - ); - - $shopConfigMock = $this->createPartialMock(Config::class, ['getConfigParam']); - $shopConfigMock->expects($this->any()) - ->method('getConfigParam') - ->with('sShopDir') - ->willReturn('someShopDir/'); - - $sut = $this->getSut( - moduleSettings: $moduleSettingsMock, - shopConfig: $shopConfigMock - ); - - $mediaPath = $sut->getMediaPath($file); - - $this->assertSame('someShopDir' . Media::MEDIA_PATH . $file, $mediaPath); - } - - /** - * @dataProvider getImagePathDataProvider - */ - public function testGetMediaPathWithAlternativeUrl($file) - { - $externalUrl = 'https://some-cdn-url.com'; - $moduleSettingsMock = $this->createConfiguredMock( - ModuleSettings::class, - [ - 'getAlternativeImageDirectory' => $externalUrl, - ] - ); - - $sut = $this->getSut(moduleSettings: $moduleSettingsMock); - $mediaPath = $sut->getMediaPath($file); - - $this->assertSame($externalUrl . Media::MEDIA_PATH_SHORT . $file, $mediaPath); - } - - /** - * @dataProvider getImagePathDataProvider - */ - public function testGetMediaUrlNoAlternativeUrl($file) - { - $externalUrl = 'https://some-cdn-url.com'; - $aFilepath = explode('/', $file); - if (count($aFilepath) > 1) { - $filename = [ - $aFilepath[0] => [ - $aFilepath[1] => 'file content', - ], - ]; - } else { - $filename = [ - $aFilepath[0] => 'file content', - ]; - } - $structure = [ - 'out' => [ - 'pictures' => [ - 'ddmedia' => $filename, - ], - ], - ]; - $directory = vfsStream::setup('root', 0777, $structure); - - $moduleSettingsMock = $this->createConfiguredMock( - ModuleSettings::class, - [ - 'getAlternativeImageDirectory' => '', - ] - ); - - $shopConfigMock = $this->createPartialMock(Config::class, ['getConfigParam', 'getSslShopUrl']); - $shopConfigMock->expects($this->any()) - ->method('getConfigParam') - ->willReturnMap( - [ - ['sShopDir', null, $directory->url()], - ] - ); - $shopConfigMock->expects($this->any()) - ->method('getSslShopUrl') - ->willReturn($externalUrl); - - $sut = $this->getSut( - moduleSettings: $moduleSettingsMock, - shopConfig: $shopConfigMock - ); - - $this->assertSame($externalUrl . Media::MEDIA_PATH . $file, $sut->getMediaUrl($file)); - } - - /** - * @dataProvider getImagePathDataProvider - */ - public function testGetMediaUrlNotExistingFile($file) - { - $moduleSettingsMock = $this->createConfiguredMock( - ModuleSettings::class, - [ - 'getAlternativeImageDirectory' => '', - ] - ); - - $shopConfigMock = $this->createPartialMock(Config::class, ['getConfigParam']); - $shopConfigMock->expects($this->any()) - ->method('getConfigParam') - ->willReturnMap( - [ - ['sShopDir', null, ''], - ] - ); - - $sut = $this->getSut( - moduleSettings: $moduleSettingsMock, - shopConfig: $shopConfigMock - ); - - $this->assertSame(false, $sut->getMediaUrl($file)); - } - - /** - * @dataProvider getImagePathDataProvider - */ - public function testGetMediaUrlWithAlternativeUrl($file) - { - $externalUrl = 'https://some-cdn-url.com'; - $moduleSettingsMock = $this->createConfiguredMock( - ModuleSettings::class, - [ - 'getAlternativeImageDirectory' => $externalUrl, - ] - ); - - $sut = $this->getSut(moduleSettings: $moduleSettingsMock); - $mediaPath = $sut->getMediaUrl($file); - - $this->assertSame($externalUrl . Media::MEDIA_PATH_SHORT . $file, $mediaPath); - } - - /** - * @dataProvider getThumbnailPathDataProvider - */ - public function testGetThumbnailPath($file, $expectedPath) - { - $path = "somePath"; - - $sut = $this->createPartialMock(Media::class, ["getMediaPath"]); - $sut->expects($this->any())->method("getMediaPath")->willReturn($path); - - $this->assertSame($expectedPath, $sut->getThumbnailPath($file)); - } - public function testCreateFolderWithNewName() { $structure = [ @@ -226,9 +65,8 @@ public function testCreateFolderWithNewName() $sut = $this->getSut( shopConfig: $shopConfigMock, connectionProvider: $connectionProviderStub, - utilsObject: $utilsObjectMock + utilsObject: $utilsObjectMock, ); - $aCustomDir = $sut->createCustomDir('FolderTest', ''); $aExpected = ['id' => $sId, 'dir' => 'FolderTest']; @@ -280,9 +118,8 @@ public function testCreateFolderWithExistingName() $sut = $this->getSut( shopConfig: $shopConfigMock, connectionProvider: $connectionProviderStub, - utilsObject: $utilsObjectMock + utilsObject: $utilsObjectMock, ); - $aCustomDir = $sut->createCustomDir('FolderTest', ''); $aExpected = ['id' => $sId, 'dir' => 'FolderTest_1']; @@ -322,11 +159,10 @@ public function testRename($structure, $oldName, $newName, $structureExpected, $ $sut = $this->getSut( shopConfig: $shopConfigMock, - connectionProvider: $connectionProviderStub + connectionProvider: $connectionProviderStub, ); - if ($folder) { - $sut->setFolderName($folder); + $sut->imageResource->setFolderName($folder); } $aSuccess = $sut->rename($oldName, $newName, '', $type); @@ -344,7 +180,10 @@ public function testMoveFile() $sTargetFolderID = '9999'; $sSourceFileName = self::FIXTURE_FILE; $sSourceFileID = '111'; - $sThumbName = '111_thumb_' . $this->getSut()->getDefaultThumbnailSize() . '.jpg'; + $sThumbName = $this->getImageSizeAsString( + '111_thumb_', + $this->getSut()->imageResource->getDefaultThumbnailSize() + ); $structure['out']['pictures']['ddmedia'][$sSourceFileName] = 'some file'; $structure['out']['pictures']['ddmedia']['thumbs'][$sThumbName] = 'some file'; @@ -392,7 +231,7 @@ public function testMoveFile() $sut = $this->getSut( shopConfig: $shopConfigMock, - connectionProvider: $connectionProviderStub + connectionProvider: $connectionProviderStub, ); $sut->moveFileToFolder($sSourceFileID, $sTargetFolderID, $sThumbName); @@ -457,11 +296,10 @@ public function testDelete($structure, $structureExpected, $aIds, $aDBData, $sta $sut = $this->getSut( shopConfig: $shopConfigMock, - connectionProvider: $connectionProviderStub + connectionProvider: $connectionProviderStub, ); - if ($startFolder) { - $sut->setFolderName($startFolder); + $sut->imageResource->setFolderName($startFolder); } $sut->delete($aIds); @@ -471,82 +309,20 @@ public function testDelete($structure, $structureExpected, $aIds, $aDBData, $sta ); } - public function testGetMediaUrl() - { - $sThumbName = md5(self::FIXTURE_FILE) . '_thumb_' . $this->getSut()->getDefaultThumbnailSize() . '.jpg'; - $structure['out']['pictures']['ddmedia'][self::FIXTURE_FILE] = 'some file'; - $structure['out']['pictures']['ddmedia']['thumbs'][$sThumbName] = 'some file'; - $anotherFile = 'file2.jpg'; - $sThumbName = md5($anotherFile) . '_thumb_' . $this->getSut()->getDefaultThumbnailSize() . '.jpg'; - $structure['out']['pictures']['ddmedia'][self::FIXTURE_FOLDER][$anotherFile] = 'some file'; - $structure['out']['pictures']['ddmedia'][self::FIXTURE_FOLDER]['thumbs'][$sThumbName] = 'some file'; - - $directory = vfsStream::setup('root', 0777, $structure); - - $shopConfigMock = $this->createPartialMock(Config::class, ['getConfigParam']); - $shopConfigMock->expects($this->any()) - ->method('getConfigParam') - ->willReturnMap( - [ - ['sShopDir', null, $directory->url()], - ['sSSLShopURL', null, 'https://test.com'], - ] - ); - $sut = $this->getSut( - shopConfig: $shopConfigMock - ); - - $sMediaUrl = $sut->getMediaUrl(self::FIXTURE_FOLDER . '/' . $anotherFile); - $this->assertEquals( - 'https://test.com/out/pictures/ddmedia/' . self::FIXTURE_FOLDER . '/' . $anotherFile, - $sMediaUrl - ); - - $sMediaUrl = $sut->getMediaUrl(self::FIXTURE_FILE); - $this->assertEquals( - 'https://test.com/out/pictures/ddmedia/' . self::FIXTURE_FILE, - $sMediaUrl - ); - } - - /** - * @dataProvider getThumbnailUrlProvider - * - * @return void - */ - public function testGetThumbnailUrl($sFile, $iThumbSize, $expected) - { - $sThumbName = md5(self::FIXTURE_FILE) . '_thumb_' . $this->getSut()->getDefaultThumbnailSize() . '.jpg'; - $structure['out']['pictures']['ddmedia']['thumbs'] = []; - $structure['out']['pictures']['ddmedia'][self::FIXTURE_FILE] = 'some file'; - $structure['out']['pictures']['ddmedia']['thumbs'][$sThumbName] = 'some file'; - $directory = vfsStream::setup('root', 0777, $structure); - $shopConfigMock = $this->createPartialMock(Config::class, ['getConfigParam']); - $shopConfigMock->expects($this->any()) - ->method('getConfigParam') - ->willReturnMap( - [ - ['sShopDir', null, $directory->url()], - ['sSSLShopURL', null, 'https://test.com'], - ] - ); - $sut = $this->getSut(shopConfig: $shopConfigMock); - - $result = $sut->getThumbnailUrl($sFile, $iThumbSize); - - $this->assertEquals($expected ? ('https://test.com/out/pictures/ddmedia/' . $expected) : $expected, $result); - } - public function testUploadMedia() { - $sThumbName = md5(self::FIXTURE_FILE) . '_thumb_' . $this->getSut()->getDefaultThumbnailSize() . '.jpg'; + $sThumbName = $this->getImageSizeAsString( + md5(self::FIXTURE_FILE) . '_thumb_', + $this->getSut()->imageResource->getDefaultThumbnailSize() + ); $sFile2 = 'file_1.jpg'; - $sThumbName1 = md5($sFile2) . '_thumb_' . $this->getSut()->getDefaultThumbnailSize() . '.jpg'; - $sThumbName2 = md5($sFile2) . '_thumb_300.jpg'; - $sThumbName3 = md5($sFile2) . '_thumb_800.jpg'; + $sThumbName1 = $this->getImageSizeAsString( + md5($sFile2) . '_thumb_', + $this->getSut()->imageResource->getDefaultThumbnailSize() + ); $structure['out']['pictures']['ddmedia'] = [ self::FIXTURE_FILE => 'some file', - 'thumbs' => [$sThumbName => 'some file'], + 'thumbs' => [$sThumbName => 'some file',$sThumbName1 => 'some file'], ]; $structure['tmp'] = ['uploaded.jpg' => 'some file']; $directory = vfsStream::setup('root', 0777, $structure); @@ -586,11 +362,11 @@ public function testUploadMedia() $sut = $this->getSut( shopConfig: $shopConfigMock, connectionProvider: $connectionProviderStub, - utilsObject: $utilsObjectMock + utilsObject: $utilsObjectMock, ); $sSourcePath = $directory->url() . '/tmp/uploaded.jpg'; - $sDestPath = $sut->getMediaPath() . self::FIXTURE_FILE; + $sDestPath = $sut->imageResource->getMediaPath() . self::FIXTURE_FILE; $sFileSize = '1024'; $sFileType = 'image/jpeg'; $sut->uploadMedia($sSourcePath, $sDestPath, $sFileSize, $sFileType, true); @@ -605,8 +381,6 @@ public function testUploadMedia() 'thumbs' => [ $sThumbName => 'some file', $sThumbName1 => 'some file', - $sThumbName2 => 'some file', - $sThumbName3 => 'some file', ], ], ], @@ -617,38 +391,12 @@ public function testUploadMedia() vfsStream::inspect(new vfsStreamStructureVisitor(), $directory)->getStructure() ); - $sDestPath = $sut->getMediaPath() . 'test.js'; + $sDestPath = $sut->imageResource->getMediaPath() . 'test.js'; $sFileType = 'text/javascript'; $this->expectException(\Exception::class); $sut->uploadMedia($sSourcePath, $sDestPath, $sFileSize, $sFileType, true); } - public function getThumbnailPathDataProvider(): array - { - return [ - [ - 'file' => 'somefile.jpg', - 'expectedPath' => 'somePath/thumbs/somefile.jpg', - ], - [ - 'file' => '', - 'expectedPath' => 'somePath/thumbs', - ], - ]; - } - - public function getImagePathDataProvider(): array - { - return [ - [ - 'file' => self::FIXTURE_FILE, - ], - [ - 'file' => self::FIXTURE_FOLDER . '/' . self::FIXTURE_FILE, - ], - ]; - } - public function getRenameDataProvider(): array { $oMedia = new Media( @@ -656,18 +404,30 @@ public function getRenameDataProvider(): array $this->createStub(Config::class), $this->createStub(ConnectionProviderInterface::class), $this->createStub(UtilsObject::class), - $this->createStub(ThumbnailGeneratorInterface::class) + $this->createStub(ThumbnailGeneratorInterface::class), + $this->createStub(ImageResourceInterface::class), ); - $sThumbName = md5(self::FIXTURE_FILE) . '_thumb_' . $oMedia->getDefaultThumbnailSize() . '.jpg'; - $sThumbNameNew = md5('new.jpg') . '_thumb_' . $oMedia->getDefaultThumbnailSize() . '.jpg'; + $defaultThumbnailSize = $oMedia->imageResource->getDefaultThumbnailSize(); + + $sThumbName = $this->getImageSizeAsString( + md5(self::FIXTURE_FILE) . '_thumb_', + $defaultThumbnailSize + ); + $sThumbNameNew = $this->getImageSizeAsString( + md5('new.jpg') . '_thumb_', + $defaultThumbnailSize + ); $structure['out']['pictures']['ddmedia'][self::FIXTURE_FILE] = 'some file'; $structure['out']['pictures']['ddmedia']['thumbs'][$sThumbName] = 'some file'; $structureExpected['root']['out']['pictures']['ddmedia']['new.jpg'] = 'some file'; $structureExpected['root']['out']['pictures']['ddmedia']['thumbs'][$sThumbNameNew] = 'some file'; - $sThumbName = md5(self::FIXTURE_FILE) . '_thumb_' . $oMedia->getDefaultThumbnailSize() . '.jpg'; + $sThumbName = $this->getImageSizeAsString( + md5(self::FIXTURE_FILE) . '_thumb_', + $defaultThumbnailSize + ); $structure1['out']['pictures']['ddmedia'][self::FIXTURE_FOLDER][self::FIXTURE_FILE] = 'some file'; $structure1['out']['pictures']['ddmedia'][self::FIXTURE_FOLDER]['thumbs'][$sThumbName] = 'some file'; $structureExpected1 = [ @@ -690,10 +450,22 @@ public function getRenameDataProvider(): array $structure2['out']['pictures']['ddmedia'][self::FIXTURE_FOLDER] = []; $structureExpected2['root']['out']['pictures']['ddmedia']['folderNew'] = []; - $sThumbName = md5(self::FIXTURE_FILE) . '_thumb_' . $oMedia->getDefaultThumbnailSize() . '.jpg'; - $sThumbName2 = md5('new_1.jpg') . '_thumb_' . $oMedia->getDefaultThumbnailSize() . '.jpg'; - $sThumbName3 = md5('new_1.jpg') . '_thumb_' . $oMedia->getDefaultThumbnailSize() . '.jpg'; - $sThumbNameNew2 = md5('new_2.jpg') . '_thumb_' . $oMedia->getDefaultThumbnailSize() . '.jpg'; + $sThumbName = $this->getImageSizeAsString( + md5(self::FIXTURE_FILE) . '_thumb_', + $defaultThumbnailSize + ); + $sThumbName2 = $this->getImageSizeAsString( + md5('new_1.jpg') . '_thumb_', + $defaultThumbnailSize + ); + $sThumbName3 = $this->getImageSizeAsString( + md5('new_1.jpg') . '_thumb_', + $defaultThumbnailSize + ); + $sThumbNameNew2 = $this->getImageSizeAsString( + md5('new_2.jpg') . '_thumb_', + $defaultThumbnailSize + ); $structure3['out']['pictures']['ddmedia'][self::FIXTURE_FOLDER][self::FIXTURE_FILE] = 'some file'; $structure3['out']['pictures']['ddmedia'][self::FIXTURE_FOLDER]['new.jpg'] = 'some file'; $structure3['out']['pictures']['ddmedia'][self::FIXTURE_FOLDER]['new_1.jpg'] = 'some file'; @@ -763,14 +535,11 @@ public function getRenameDataProvider(): array public function getDeleteDataProvider() { - $oMedia = new Media( - $this->createStub(ModuleSettings::class), - $this->createStub(Config::class), - $this->createStub(ConnectionProviderInterface::class), - $this->createStub(UtilsObject::class), - $this->createStub(ThumbnailGeneratorInterface::class) + $oMedia = $this->getSut(); + $sThumbName = $this->getImageSizeAsString( + '111_thumb_', + $oMedia->imageResource->getDefaultThumbnailSize() ); - $sThumbName = '111_thumb_' . $oMedia->getDefaultThumbnailSize() . '.jpg'; // scenario 1 - file in media root $structure['out']['pictures']['ddmedia'][self::FIXTURE_FILE] = 'some file'; @@ -863,36 +632,6 @@ public function getDeleteDataProvider() ]; } - public function getThumbnailUrlProvider() - { - $oMedia = new Media( - $this->createStub(ModuleSettings::class), - $this->createStub(Config::class), - $this->createStub(ConnectionProviderInterface::class), - $this->createStub(UtilsObject::class), - $this->createStub(ThumbnailGeneratorInterface::class) - ); - $sThumbName = md5(self::FIXTURE_FILE) . '_thumb_' . $oMedia->getDefaultThumbnailSize() . '.jpg'; - - return [ - [ - 'sFile' => '', - 'iThumbSize' => null, - 'expected' => 'thumbs', - ], - [ - 'sFile' => self::FIXTURE_FILE, - 'iThumbSize' => null, - 'expected' => 'thumbs/' . $sThumbName, - ], - [ - 'sFile' => '111.jpg', - 'iThumbSize' => null, - 'expected' => false, - ], - ]; - } - protected function getSut( ?ModuleSettings $moduleSettings = null, ?Config $shopConfig = null, @@ -900,12 +639,45 @@ protected function getSut( ?UtilsObject $utilsObject = null, ?ThumbnailGeneratorInterface $thumbnailGenerator = null ) { + + $imageResourceMock = $this->getImageResourceStub( + $shopConfig, + $moduleSettings, + $thumbnailGenerator, + $connectionProvider + ); return new MediaMock( $moduleSettings ?: $this->createStub(ModuleSettings::class), $shopConfig ?: $this->createStub(Config::class), $connectionProvider ?: $this->createStub(ConnectionProviderInterface::class), $utilsObject ?: $this->createStub(UtilsObject::class), - $thumbnailGenerator ?: $this->createStub(ThumbnailGeneratorInterface::class) + $thumbnailGenerator ?: $this->createStub(ThumbnailGeneratorInterface::class), + $imageResourceMock + ); + } + + protected function getImageResourceStub( + ?Config $shopConfig = null, + ?ModuleSettings $moduleSettings = null, + ?ThumbnailGeneratorInterface $thumbnailGenerator = null, + ?ConnectionProviderInterface $connectionProvider = null, + ) { + return new ImageResource( + $shopConfig ?: $this->createStub(Config::class), + $moduleSettings ?: $this->createStub(ModuleSettings::class), + $thumbnailGenerator ?: $this->createStub(ThumbnailGeneratorInterface::class), + $connectionProvider ?: $this->createStub(ConnectionProviderInterface::class), + ); + } + + private function getImageSizeAsString(string $prefix, int $imageSize, $suffix = '.jpg'): string + { + return sprintf( + '%s%d*%d%s', + $prefix, + $imageSize, + $imageSize, + $suffix ); } }