Skip to content

Commit

Permalink
Extra check if image is not used by other product
Browse files Browse the repository at this point in the history
  • Loading branch information
patrick-bigbridge committed Oct 8, 2018
1 parent a00d36c commit b1a33ea
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 7 deletions.
37 changes: 33 additions & 4 deletions Model/Resource/Storage/ImageStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,27 @@ protected function removeObsoleteImages(Product $product, array $existingImages,
[$storagePath]
));

// remove from file system
@unlink(self::PRODUCT_IMAGE_PATH . $storagePath);
// check if the image is used by other products
// (this cannot be the case in standard Magento)
$usageCount = $this->db->fetchSingleCell("
SELECT COUNT(*)
FROM `{$this->metaData->productEntityTable}_varchar`
WHERE
attribute_id IN (" . $this->db->getMarks($this->metaData->imageAttributeIds) . ") AND
value = ?
", array_merge(
$this->metaData->imageAttributeIds,
[$storagePath]
));

// only remove image from filesystem if it is not used by other products
// note! this only checks if the image has a role in a product, not if it is used in a gallery
// the real check would be too slow
if ($usageCount == 0) {
// remove from file system
@unlink(self::PRODUCT_IMAGE_PATH . $storagePath);
}

}
}

Expand All @@ -284,6 +303,7 @@ protected function removeObsoleteImages(Product $product, array $existingImages,

/**
* Load data from existing product images
* Returns image.jpg before image_1.jpg, image_2.jpg, ...
*
* @param Product $product
*/
Expand All @@ -293,13 +313,22 @@ protected function loadExistingImageData(Product $product)
SELECT M.`value_id`, M.`value`, M.`disabled`
FROM {$this->metaData->mediaGalleryTable} M
INNER JOIN {$this->metaData->mediaGalleryValueToEntityTable} E ON E.`value_id` = M.`value_id`
WHERE E.`entity_id` = ? AND M.`attribute_id` = ?
WHERE E.`entity_id` = ? AND M.`attribute_id` = ?
ORDER BY M.`value_id`
", [
$product->id,
$this->metaData->mediaGalleryAttributeId
]);
}

/**
* An image "exists" if its path is stored in the database gallery for this product (perhaps with a suffix)
* otherwise it is "new".
*
* @param Product $product
* @param array $imageData
* @return array
*/
public function splitNewAndExistingImages(Product $product, array $imageData)
{
$existingImages = [];
Expand All @@ -317,7 +346,7 @@ public function splitNewAndExistingImages(Product $product, array $imageData)
if ($simpleStoragePath === $image->getDefaultStoragePath()) {
$found = true;
$image->valueId = $imageDatum['value_id'];
$image->setActualStoragePath($imageDatum['value']);
$image->setActualStoragePath($storagePath);
break;
}
}
Expand Down
10 changes: 9 additions & 1 deletion Test/Integration/ImportTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ public function testMissingCategories()
public function testImages()
{
@unlink(BP . '/pub/media/catalog/product/d/u/duck1.jpg');
@unlink(BP . '/pub/media/catalog/product/d/u/duck1_1.jpg');
@unlink(BP . '/pub/media/catalog/product/d/u/duck2.png');
@unlink(BP . '/pub/media/catalog/product/d/u/duck3.png');
@unlink(BP . '/pub/media/catalog/product/d/u/duck3_1.png');
Expand Down Expand Up @@ -468,6 +469,7 @@ public function testImages()

$this->assertEquals([], $errors);
$this->assertTrue(file_exists(BP . '/pub/media/catalog/product/d/u/duck1.jpg'));
$this->assertFalse(file_exists(BP . '/pub/media/catalog/product/d/u/duck1_1.jpg'));
$this->assertTrue(file_exists(BP . '/pub/media/catalog/product/d/u/duck2.png'));

$media = [
Expand Down Expand Up @@ -536,6 +538,7 @@ public function testImages()

$productS = self::$repository->get("ducky1-product-import", false, 0, true);
$this->assertEquals('/d/u/duck1.jpg', $productS->getThumbnail());
$this->assertFalse(file_exists(BP . '/pub/media/catalog/product/d/u/duck1_1.jpg'));
$this->assertEquals('/d/u/duck2.png', $productS->getImage());
$this->assertEquals('/d/u/duck3_1.png', $productS->getSmallImage());

Expand Down Expand Up @@ -575,6 +578,7 @@ public function testImages()

$this->assertEquals([], $errors);
$this->assertTrue(file_exists(BP . '/pub/media/catalog/product/d/u/duck1.jpg'));
$this->assertFalse(file_exists(BP . '/pub/media/catalog/product/d/u/duck1_1.jpg'));
$this->assertFalse(file_exists(BP . '/pub/media/catalog/product/d/u/duck2.png'));

$media = [
Expand Down Expand Up @@ -607,6 +611,7 @@ public function testImages()

$this->assertEquals([], $errors);
$this->assertTrue(file_exists(BP . '/pub/media/catalog/product/d/u/duck1.jpg'));
$this->assertFalse(file_exists(BP . '/pub/media/catalog/product/d/u/duck1_1.jpg'));
$this->assertFalse(file_exists(BP . '/pub/media/catalog/product/d/u/duck2.png'));

$media = [
Expand All @@ -623,7 +628,6 @@ public function testImages()
$this->assertEquals('/d/u/duck1.jpg', $productS->getThumbnail());
$this->assertEquals(null, $productS->getImage());
$this->assertEquals(null, $productS->getSmallImage());

}

private function checkImageData($product, $mediaData, $valueData)
Expand Down Expand Up @@ -1676,6 +1680,10 @@ private function checkDownloadable($downloadable) {
$this->assertTrue(file_exists(BP . "/pub/media/downloadable/files/samples/d/u/duck3.png"));

$this->assertTrue(!file_exists(BP . "/pub/media/downloadable/files/links/d/u/duck1_1.jpg"));

@unlink(BP . '/pub/media/downloadable/files/links/d/u/duck1.jpg');
@unlink(BP . '/pub/media/downloadable/files/link_samples/d/u/duck2.png');
@unlink(BP . '/pub/media/downloadable/files/samples/d/u/duck3.png');
}

/**
Expand Down
2 changes: 2 additions & 0 deletions Test/Integration/ValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ public function testImageValidation()

public function testImageRoleValidation()
{
@unlink(BP . '/pub/media/catalog/product/d/u/duck1.jpg');

$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();

/** @var Validator $validator */
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bigbridge/product-import",
"description": "Imports products with raw database queries",
"description": "Fast product import library for Magento 2",
"type": "magento2-module",
"require": {
"php": "~7.0"
Expand Down
4 changes: 3 additions & 1 deletion doc/design-considerations.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,11 @@ https://sourceforge.net/p/magmi/patches/23/

## Images

All images are places in a temporary location in the validation phase, before being processed further. This ensures that all images are valid when being processed.
All images are placed in a temporary location in the validation phase, before being processed further. This ensures that all images are valid when being processed.
Make sure to remove all images from their temporary location later.

When an image is updated, the library must check if a database entry exists for this image and if the file still exists that belongs to this database entry.

## Default values

I came back from the idea of setting default values (attribute_set_id, visibility, etc) for new products. They slow the importer down a bit, they make the system a little less flexible , and they provide a false sense of security. I want to make the user think at least a few minutes about these values. She will have to do this eventually anyway. And they were some attributes that I could not settle on to make them defaults (url_key, website_ids).
Expand Down

0 comments on commit b1a33ea

Please sign in to comment.