2323use Magento \Framework \Exception \NoSuchEntityException ;
2424use Magento \Framework \Filesystem ;
2525use Magento \Framework \Filesystem \Driver \File ;
26+ use Magento \Framework \Filesystem \DriverPool ;
2627use Magento \Framework \Intl \DateTimeFactory ;
2728use Magento \Framework \Model \ResourceModel \Db \ObjectRelationProcessor ;
2829use Magento \Framework \Model \ResourceModel \Db \TransactionManagerInterface ;
@@ -767,11 +768,6 @@ class Product extends AbstractEntity
767768 */
768769 private $ linkProcessor ;
769770
770- /**
771- * @var File
772- */
773- private $ fileDriver ;
774-
775771 /**
776772 * @param \Magento\Framework\Json\Helper\Data $jsonHelper
777773 * @param \Magento\ImportExport\Helper\Data $importExportData
@@ -938,7 +934,6 @@ public function __construct(
938934 $ this ->dateTimeFactory = $ dateTimeFactory ?? ObjectManager::getInstance ()->get (DateTimeFactory::class);
939935 $ this ->productRepository = $ productRepository ?? ObjectManager::getInstance ()
940936 ->get (ProductRepositoryInterface::class);
941- $ this ->fileDriver = $ fileDriver ?: ObjectManager::getInstance ()->get (File::class);
942937 }
943938
944939 /**
@@ -1580,7 +1575,6 @@ protected function _saveProducts()
15801575 $ previousType = null ;
15811576 $ prevAttributeSet = null ;
15821577
1583- $ importDir = $ this ->_mediaDirectory ->getAbsolutePath ($ this ->getUploader ()->getTmpDir ());
15841578 $ existingImages = $ this ->getExistingImages ($ bunch );
15851579 $ this ->addImageHashes ($ existingImages );
15861580
@@ -1750,7 +1744,10 @@ protected function _saveProducts()
17501744 $ position = 0 ;
17511745 foreach ($ rowImages as $ column => $ columnImages ) {
17521746 foreach ($ columnImages as $ columnImageKey => $ columnImage ) {
1753- $ uploadedFile = $ this ->getAlreadyExistedImage ($ rowExistingImages , $ columnImage , $ importDir );
1747+ $ hash = filter_var ($ columnImage , FILTER_VALIDATE_URL )
1748+ ? $ this ->getRemoteFileHash ($ columnImage )
1749+ : $ this ->getFileHash ($ this ->joinFilePaths ($ this ->getUploader ()->getTmpDir (), $ columnImage ));
1750+ $ uploadedFile = $ this ->findImageByHash ($ rowExistingImages , $ hash );
17541751 if (!$ uploadedFile && !isset ($ uploadedImages [$ columnImage ])) {
17551752 $ uploadedFile = $ this ->uploadMediaFiles ($ columnImage );
17561753 $ uploadedFile = $ uploadedFile ?: $ this ->getSystemFile ($ columnImage );
@@ -1955,40 +1952,29 @@ protected function _saveProducts()
19551952 *
19561953 * @param string $path
19571954 * @return string
1955+ * @throws \Magento\Framework\Exception\FileSystemException
19581956 */
19591957 private function getFileHash (string $ path ): string
19601958 {
1961- return hash_file (self ::HASH_ALGORITHM , $ path );
1959+ $ content = '' ;
1960+ if ($ this ->_mediaDirectory ->isFile ($ path )
1961+ && $ this ->_mediaDirectory ->isReadable ($ path )
1962+ ) {
1963+ $ content = $ this ->_mediaDirectory ->readFile ($ path );
1964+ }
1965+ return $ content ? hash (self ::HASH_ALGORITHM , $ content ) : '' ;
19621966 }
19631967
19641968 /**
1965- * Returns existed image
1969+ * Returns hash for remote file
19661970 *
1967- * @param array $imageRow
1968- * @param string $columnImage
1969- * @param string $importDir
1971+ * @param string $filename
19701972 * @return string
19711973 */
1972- private function getAlreadyExistedImage ( array $ imageRow , string $ columnImage , string $ importDir ): string
1974+ private function getRemoteFileHash ( string $ filename ): string
19731975 {
1974- if (filter_var ($ columnImage , FILTER_VALIDATE_URL )) {
1975- $ hash = $ this ->getFileHash ($ columnImage );
1976- } else {
1977- $ path = $ importDir . DIRECTORY_SEPARATOR . $ columnImage ;
1978- $ hash = $ this ->isFileExists ($ path ) ? $ this ->getFileHash ($ path ) : '' ;
1979- }
1980-
1981- return array_reduce (
1982- $ imageRow ,
1983- function ($ exists , $ file ) use ($ hash ) {
1984- if (!$ exists && isset ($ file ['hash ' ]) && $ file ['hash ' ] === $ hash ) {
1985- return $ file ['value ' ];
1986- }
1987-
1988- return $ exists ;
1989- },
1990- ''
1991- );
1976+ $ hash = hash_file (self ::HASH_ALGORITHM , $ filename );
1977+ return $ hash !== false ? $ hash : '' ;
19921978 }
19931979
19941980 /**
@@ -1999,38 +1985,19 @@ function ($exists, $file) use ($hash) {
19991985 */
20001986 private function addImageHashes (array &$ images ): void
20011987 {
2002- $ productMediaPath = $ this ->filesystem ->getDirectoryRead (DirectoryList::MEDIA )
2003- ->getAbsolutePath (DIRECTORY_SEPARATOR . 'catalog ' . DIRECTORY_SEPARATOR . 'product ' );
2004-
1988+ $ productMediaPath = $ this ->getProductMediaPath ();
20051989 foreach ($ images as $ storeId => $ skus ) {
20061990 foreach ($ skus as $ sku => $ files ) {
20071991 foreach ($ files as $ path => $ file ) {
2008- if ( $ this ->fileDriver -> isExists ($ productMediaPath . $ file ['value ' ])) {
2009- $ fileName = $ productMediaPath . $ file [ ' value ' ];
2010- $ images [$ storeId ][$ sku ][$ path ]['hash ' ] = $ this -> getFileHash ( $ fileName ) ;
1992+ $ hash = $ this ->getFileHash ( $ this -> joinFilePaths ($ productMediaPath, $ file ['value ' ]));
1993+ if ( $ hash ) {
1994+ $ images [$ storeId ][$ sku ][$ path ]['hash ' ] = $ hash ;
20111995 }
20121996 }
20131997 }
20141998 }
20151999 }
20162000
2017- /**
2018- * Is file exists
2019- *
2020- * @param string $path
2021- * @return bool
2022- */
2023- private function isFileExists (string $ path ): bool
2024- {
2025- try {
2026- $ fileExists = $ this ->fileDriver ->isExists ($ path );
2027- } catch (\Exception $ exception ) {
2028- $ fileExists = false ;
2029- }
2030-
2031- return $ fileExists ;
2032- }
2033-
20342001 /**
20352002 * Clears entries from Image Set and Row Data marked as no_selection
20362003 *
@@ -2214,23 +2181,15 @@ protected function _getUploader()
22142181
22152182 $ fileUploader ->init ();
22162183
2217- $ dirConfig = DirectoryList::getDefaultConfig ();
2218- $ dirAddon = $ dirConfig [DirectoryList::MEDIA ][DirectoryList::PATH ];
2219-
2220- // make media folder a primary folder for media in external storages
2221- if (!is_a ($ this ->_mediaDirectory ->getDriver (), File::class)) {
2222- $ dirAddon = DirectoryList::MEDIA ;
2223- }
2224-
22252184 $ tmpPath = $ this ->getImportDir ();
22262185
22272186 if (!$ fileUploader ->setTmpDir ($ tmpPath )) {
22282187 throw new LocalizedException (
22292188 __ ('File directory \'%1 \' is not readable. ' , $ tmpPath )
22302189 );
22312190 }
2232- $ destinationDir = " catalog/product " ;
2233- $ destinationPath = $ dirAddon . ' / ' . $ this ->_mediaDirectory -> getRelativePath ( $ destinationDir );
2191+
2192+ $ destinationPath = $ this ->getProductMediaPath ( );
22342193
22352194 $ this ->_mediaDirectory ->create ($ destinationPath );
22362195 if (!$ fileUploader ->setDestDir ($ destinationPath )) {
@@ -2284,11 +2243,11 @@ protected function uploadMediaFiles($fileName, $renameFileOff = false)
22842243 */
22852244 private function getSystemFile ($ fileName )
22862245 {
2287- $ filePath = 'catalog ' . DIRECTORY_SEPARATOR . 'product ' . DIRECTORY_SEPARATOR . $ fileName ;
2288- /** @var \Magento\Framework\Filesystem\Directory\ReadInterface $read */
2289- $ read = $ this ->filesystem ->getDirectoryRead (DirectoryList::MEDIA );
2246+ $ filePath = $ this ->joinFilePaths ($ this ->getProductMediaPath (), $ fileName );
22902247
2291- return $ read ->isExist ($ filePath ) && $ read ->isReadable ($ filePath ) ? $ fileName : '' ;
2248+ return $ this ->_mediaDirectory ->isFile ($ filePath ) && $ this ->_mediaDirectory ->isReadable ($ filePath )
2249+ ? $ fileName
2250+ : '' ;
22922251 }
22932252
22942253 /**
@@ -3280,4 +3239,68 @@ private function getRowExistingStockItem(array $rowData): StockItemInterface
32803239 $ websiteId = $ this ->stockConfiguration ->getDefaultScopeId ();
32813240 return $ this ->stockRegistry ->getStockItem ($ productId , $ websiteId );
32823241 }
3242+
3243+ /**
3244+ * Returns image that matches the provided hash
3245+ *
3246+ * @param array $images
3247+ * @param string $hash
3248+ * @return string
3249+ */
3250+ private function findImageByHash (array $ images , string $ hash ): string
3251+ {
3252+ $ value = '' ;
3253+ if ($ hash ) {
3254+ foreach ($ images as $ image ) {
3255+ if (isset ($ image ['hash ' ]) && $ image ['hash ' ] === $ hash ) {
3256+ $ value = $ image ['value ' ];
3257+ break ;
3258+ }
3259+ }
3260+ }
3261+ return $ value ;
3262+ }
3263+
3264+ /**
3265+ * Returns product media
3266+ *
3267+ * @return string relative path to root folder
3268+ */
3269+ private function getProductMediaPath (): string
3270+ {
3271+ return $ this ->joinFilePaths ($ this ->getMediaBasePath (), 'catalog ' ,'product ' );
3272+ }
3273+
3274+ /**
3275+ * Returns media base path
3276+ *
3277+ * @return string relative path to root folder
3278+ */
3279+ private function getMediaBasePath (): string
3280+ {
3281+ $ mediaDir = !is_a ($ this ->_mediaDirectory ->getDriver (), File::class)
3282+ // make media folder a primary folder for media in external storages
3283+ ? $ this ->filesystem ->getDirectoryReadByPath (DirectoryList::MEDIA )
3284+ : $ this ->filesystem ->getDirectoryRead (DirectoryList::MEDIA );
3285+
3286+ return $ this ->_mediaDirectory ->getRelativePath ($ mediaDir ->getAbsolutePath ());
3287+ }
3288+
3289+ /**
3290+ * Joins two paths and remove redundant directory separator
3291+ *
3292+ * @param string ...$paths
3293+ * @return string
3294+ */
3295+ private function joinFilePaths (...$ paths ): string
3296+ {
3297+ $ result = '' ;
3298+ if ($ paths ) {
3299+ $ result = rtrim (array_shift ($ paths ), DIRECTORY_SEPARATOR );
3300+ foreach ($ paths as $ path ) {
3301+ $ result .= DIRECTORY_SEPARATOR . ltrim ($ path , DIRECTORY_SEPARATOR );
3302+ }
3303+ }
3304+ return $ result ;
3305+ }
32833306}
0 commit comments