fixes for image transfer
This commit is contained in:
parent
659b3705fc
commit
9ec5a56bed
|
|
@ -0,0 +1,395 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Services\MagentoCategoryMigrationService;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class TestProductImageMigration extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'test:product-images {sku=saunaheater2403}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Test migrating images for a specific product by SKU';
|
||||
|
||||
protected $migrationService;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*/
|
||||
public function __construct(MagentoCategoryMigrationService $migrationService)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->migrationService = $migrationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$sku = $this->argument('sku');
|
||||
|
||||
$this->info("Testing image migration for product SKU: {$sku}");
|
||||
$this->newLine();
|
||||
|
||||
// Get connection details from the service using reflection
|
||||
$reflection = new \ReflectionClass($this->migrationService);
|
||||
$m1ConnectionProp = $reflection->getProperty('magento1Connection');
|
||||
$m2ConnectionProp = $reflection->getProperty('magento2Connection');
|
||||
$m1PrefixProp = $reflection->getProperty('magento1Prefix');
|
||||
$m2PrefixProp = $reflection->getProperty('magento2Prefix');
|
||||
|
||||
$m1ConnectionProp->setAccessible(true);
|
||||
$m2ConnectionProp->setAccessible(true);
|
||||
$m1PrefixProp->setAccessible(true);
|
||||
$m2PrefixProp->setAccessible(true);
|
||||
|
||||
$m1Connection = $m1ConnectionProp->getValue($this->migrationService);
|
||||
$m2Connection = $m2ConnectionProp->getValue($this->migrationService);
|
||||
$m1Prefix = $m1PrefixProp->getValue($this->migrationService);
|
||||
$m2Prefix = $m2PrefixProp->getValue($this->migrationService);
|
||||
|
||||
// Step 1: Find product in M1
|
||||
$this->info("Step 1: Finding product in Magento 1...");
|
||||
$m1Product = $this->findM1ProductBySku($sku, $m1Connection, $m1Prefix);
|
||||
|
||||
if (!$m1Product) {
|
||||
$this->error("Product with SKU '{$sku}' not found in Magento 1");
|
||||
return 1;
|
||||
}
|
||||
|
||||
$m1ProductId = $m1Product->entity_id;
|
||||
$this->info("✓ Found M1 product: ID {$m1ProductId}, SKU: {$sku}");
|
||||
$this->newLine();
|
||||
|
||||
// Step 2: Check images in M1
|
||||
$this->info("Step 2: Checking images in Magento 1...");
|
||||
$m1Images = $this->getM1Images($m1ProductId, $m1Connection, $m1Prefix);
|
||||
$this->info("✓ Found " . count($m1Images) . " images in M1:");
|
||||
foreach ($m1Images as $idx => $image) {
|
||||
$this->line(" " . ($idx + 1) . ". {$image['file']} (value_id: {$image['value_id']})");
|
||||
}
|
||||
$this->newLine();
|
||||
|
||||
// Step 3: Find product in M2
|
||||
$this->info("Step 3: Finding product in Magento 2...");
|
||||
$m2Product = $this->findM2ProductBySku($sku, $m2Connection, $m2Prefix);
|
||||
|
||||
if (!$m2Product) {
|
||||
$this->error("Product with SKU '{$sku}' not found in Magento 2. Please migrate the product first.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
$m2ProductId = $m2Product->entity_id;
|
||||
$this->info("✓ Found M2 product: ID {$m2ProductId}, SKU: {$sku}");
|
||||
$this->newLine();
|
||||
|
||||
// Step 4: Check images in M2 before migration
|
||||
$this->info("Step 4: Checking images in Magento 2 BEFORE migration...");
|
||||
$m2ImagesBefore = $this->getM2Images($m2ProductId, $m2Connection, $m2Prefix);
|
||||
$this->info("✓ Found " . count($m2ImagesBefore) . " images in M2 before migration");
|
||||
if (count($m2ImagesBefore) > 0) {
|
||||
foreach ($m2ImagesBefore as $idx => $image) {
|
||||
$this->line(" " . ($idx + 1) . ". {$image['file']} (value_id: {$image['value_id']})");
|
||||
}
|
||||
}
|
||||
$this->newLine();
|
||||
|
||||
// Step 5: Migrate images
|
||||
$this->info("Step 5: Migrating images...");
|
||||
try {
|
||||
$m1EntityTypeId = DB::connection($m1Connection)
|
||||
->table($m1Prefix . 'eav_entity_type')
|
||||
->where('entity_type_code', 'catalog_product')
|
||||
->value('entity_type_id');
|
||||
|
||||
// Use reflection to call the protected method
|
||||
$reflection = new \ReflectionClass($this->migrationService);
|
||||
$method = $reflection->getMethod('migrateProductMediaGallery');
|
||||
$method->setAccessible(true);
|
||||
|
||||
$method->invoke($this->migrationService, $m1ProductId, $m2ProductId, $m1EntityTypeId);
|
||||
|
||||
$this->info("✓ Migration method executed");
|
||||
} catch (\Exception $e) {
|
||||
$this->error("✗ Error during migration: " . $e->getMessage());
|
||||
$this->error("Stack trace: " . $e->getTraceAsString());
|
||||
return 1;
|
||||
}
|
||||
$this->newLine();
|
||||
|
||||
// Step 6: Check images in M2 after migration
|
||||
$this->info("Step 6: Checking images in Magento 2 AFTER migration...");
|
||||
$m2ImagesAfter = $this->getM2Images($m2ProductId, $m2Connection, $m2Prefix);
|
||||
$this->info("✓ Found " . count($m2ImagesAfter) . " images in M2 after migration");
|
||||
|
||||
if (count($m2ImagesAfter) > 0) {
|
||||
foreach ($m2ImagesAfter as $idx => $image) {
|
||||
$this->line(" " . ($idx + 1) . ". {$image['file']} (value_id: {$image['value_id']})");
|
||||
}
|
||||
} else {
|
||||
$this->error("✗ No images found in M2 after migration!");
|
||||
}
|
||||
$this->newLine();
|
||||
|
||||
// Step 7: Compare results
|
||||
$this->info("Step 7: Comparison Results:");
|
||||
$this->line(" M1 images: " . count($m1Images));
|
||||
$this->line(" M2 images before: " . count($m2ImagesBefore));
|
||||
$this->line(" M2 images after: " . count($m2ImagesAfter));
|
||||
$this->line(" Expected: " . count($m1Images));
|
||||
$this->line(" Actual: " . count($m2ImagesAfter));
|
||||
|
||||
if (count($m2ImagesAfter) >= count($m1Images)) {
|
||||
$this->info("✓ SUCCESS: All images migrated!");
|
||||
} else {
|
||||
$this->error("✗ FAILURE: Missing " . (count($m1Images) - count($m2ImagesAfter)) . " images");
|
||||
|
||||
// Show which images are missing
|
||||
$m1Files = array_column($m1Images, 'file');
|
||||
$m2Files = array_column($m2ImagesAfter, 'file');
|
||||
$missing = array_diff($m1Files, $m2Files);
|
||||
|
||||
if (!empty($missing)) {
|
||||
$this->error("Missing images:");
|
||||
foreach ($missing as $file) {
|
||||
$this->line(" - {$file}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function findM1ProductBySku($sku, $connection, $prefix)
|
||||
{
|
||||
// Try entity table first
|
||||
try {
|
||||
$product = DB::connection($connection)
|
||||
->table($prefix . 'catalog_product_entity')
|
||||
->where('sku', $sku)
|
||||
->first();
|
||||
|
||||
if ($product) {
|
||||
return $product;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// SKU might be in EAV table
|
||||
}
|
||||
|
||||
// Try EAV table
|
||||
$entityTypeId = DB::connection($connection)
|
||||
->table($prefix . 'eav_entity_type')
|
||||
->where('entity_type_code', 'catalog_product')
|
||||
->value('entity_type_id');
|
||||
|
||||
if (!$entityTypeId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$skuAttributeId = DB::connection($connection)
|
||||
->table($prefix . 'eav_attribute')
|
||||
->where('entity_type_id', $entityTypeId)
|
||||
->where('attribute_code', 'sku')
|
||||
->value('attribute_id');
|
||||
|
||||
if (!$skuAttributeId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$skuRow = DB::connection($connection)
|
||||
->table($prefix . 'catalog_product_entity_varchar')
|
||||
->where('attribute_id', $skuAttributeId)
|
||||
->where('value', $sku)
|
||||
->where('store_id', 0)
|
||||
->first();
|
||||
|
||||
if (!$skuRow) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return DB::connection($connection)
|
||||
->table($prefix . 'catalog_product_entity')
|
||||
->where('entity_id', $skuRow->entity_id)
|
||||
->first();
|
||||
}
|
||||
|
||||
protected function findM2ProductBySku($sku, $connection, $prefix)
|
||||
{
|
||||
// Try entity table first
|
||||
try {
|
||||
$product = DB::connection($connection)
|
||||
->table($prefix . 'catalog_product_entity')
|
||||
->where('sku', $sku)
|
||||
->first();
|
||||
|
||||
if ($product) {
|
||||
return $product;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// SKU might be in EAV table
|
||||
}
|
||||
|
||||
// Try EAV table
|
||||
$entityTypeId = DB::connection($connection)
|
||||
->table($prefix . 'eav_entity_type')
|
||||
->where('entity_type_code', 'catalog_product')
|
||||
->value('entity_type_id');
|
||||
|
||||
if (!$entityTypeId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$skuAttributeId = DB::connection($connection)
|
||||
->table($prefix . 'eav_attribute')
|
||||
->where('entity_type_id', $entityTypeId)
|
||||
->where('attribute_code', 'sku')
|
||||
->value('attribute_id');
|
||||
|
||||
if (!$skuAttributeId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$skuRow = DB::connection($connection)
|
||||
->table($prefix . 'catalog_product_entity_varchar')
|
||||
->where('attribute_id', $skuAttributeId)
|
||||
->where('value', $sku)
|
||||
->where('store_id', 0)
|
||||
->first();
|
||||
|
||||
if (!$skuRow) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return DB::connection($connection)
|
||||
->table($prefix . 'catalog_product_entity')
|
||||
->where('entity_id', $skuRow->entity_id)
|
||||
->first();
|
||||
}
|
||||
|
||||
protected function getM1Images($productId, $connection, $prefix)
|
||||
{
|
||||
$images = [];
|
||||
|
||||
// Check media gallery table
|
||||
try {
|
||||
$galleryImages = DB::connection($connection)
|
||||
->table($prefix . 'catalog_product_entity_media_gallery')
|
||||
->where('entity_id', $productId)
|
||||
->get();
|
||||
|
||||
foreach ($galleryImages as $img) {
|
||||
$images[] = [
|
||||
'value_id' => $img->value_id,
|
||||
'file' => $img->value,
|
||||
'attribute_id' => $img->attribute_id ?? null,
|
||||
];
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Table might not exist
|
||||
}
|
||||
|
||||
// Also check individual image attributes
|
||||
$entityTypeId = DB::connection($connection)
|
||||
->table($prefix . 'eav_entity_type')
|
||||
->where('entity_type_code', 'catalog_product')
|
||||
->value('entity_type_id');
|
||||
|
||||
if ($entityTypeId) {
|
||||
$imageAttributes = ['image', 'small_image', 'thumbnail'];
|
||||
foreach ($imageAttributes as $attrCode) {
|
||||
$attrId = DB::connection($connection)
|
||||
->table($prefix . 'eav_attribute')
|
||||
->where('entity_type_id', $entityTypeId)
|
||||
->where('attribute_code', $attrCode)
|
||||
->value('attribute_id');
|
||||
|
||||
if ($attrId) {
|
||||
$imageValue = DB::connection($connection)
|
||||
->table($prefix . 'catalog_product_entity_varchar')
|
||||
->where('entity_id', $productId)
|
||||
->where('attribute_id', $attrId)
|
||||
->where('store_id', 0)
|
||||
->whereNotNull('value')
|
||||
->where('value', '!=', '')
|
||||
->where('value', '!=', 'no_selection')
|
||||
->value('value');
|
||||
|
||||
if ($imageValue && !in_array($imageValue, array_column($images, 'file'))) {
|
||||
$images[] = [
|
||||
'value_id' => null,
|
||||
'file' => $imageValue,
|
||||
'attribute_id' => $attrId,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $images;
|
||||
}
|
||||
|
||||
protected function getM2Images($productId, $connection, $prefix)
|
||||
{
|
||||
$images = [];
|
||||
|
||||
// Get media gallery attribute ID
|
||||
$entityTypeId = DB::connection($connection)
|
||||
->table($prefix . 'eav_entity_type')
|
||||
->where('entity_type_code', 'catalog_product')
|
||||
->value('entity_type_id');
|
||||
|
||||
if (!$entityTypeId) {
|
||||
return $images;
|
||||
}
|
||||
|
||||
$mediaGalleryAttrId = DB::connection($connection)
|
||||
->table($prefix . 'eav_attribute')
|
||||
->where('entity_type_id', $entityTypeId)
|
||||
->where('attribute_code', 'media_gallery')
|
||||
->value('attribute_id');
|
||||
|
||||
if (!$mediaGalleryAttrId) {
|
||||
return $images;
|
||||
}
|
||||
|
||||
// Get images linked to this product via value_to_entity table
|
||||
$valueIds = DB::connection($connection)
|
||||
->table($prefix . 'catalog_product_entity_media_gallery_value_to_entity')
|
||||
->where('entity_id', $productId)
|
||||
->pluck('value_id')
|
||||
->toArray();
|
||||
|
||||
if (empty($valueIds)) {
|
||||
return $images;
|
||||
}
|
||||
|
||||
$galleryImages = DB::connection($connection)
|
||||
->table($prefix . 'catalog_product_entity_media_gallery')
|
||||
->whereIn('value_id', $valueIds)
|
||||
->where('attribute_id', $mediaGalleryAttrId)
|
||||
->get();
|
||||
|
||||
foreach ($galleryImages as $img) {
|
||||
$images[] = [
|
||||
'value_id' => $img->value_id,
|
||||
'file' => $img->value,
|
||||
];
|
||||
}
|
||||
|
||||
return $images;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2195,6 +2195,7 @@ public function migrateProducts($dryRun = false)
|
|||
|
||||
// Migrate media gallery images (skip in dry run)
|
||||
if (!$dryRun) {
|
||||
Log::info("Migrating images for product SKU: {$m1Sku}, M1 ID: {$m1Product->entity_id}, M2 ID: {$m2ProductId}");
|
||||
$this->migrateProductMediaGallery($m1Product->entity_id, $m2ProductId, $m1EntityTypeId);
|
||||
}
|
||||
|
||||
|
|
@ -2515,6 +2516,7 @@ protected function migrateAllProductEntityData($m1ProductId, $m2ProductId, $m1En
|
|||
* Migrate product media gallery images from M1 to M2
|
||||
* Populates catalog_product_entity_media_gallery, catalog_product_entity_media_gallery_value,
|
||||
* and catalog_product_entity_media_gallery_value_to_entity tables
|
||||
* Also handles individual image attributes (image, small_image, thumbnail)
|
||||
*/
|
||||
protected function migrateProductMediaGallery($m1ProductId, $m2ProductId, $m1EntityTypeId)
|
||||
{
|
||||
|
|
@ -2526,11 +2528,6 @@ protected function migrateProductMediaGallery($m1ProductId, $m2ProductId, $m1Ent
|
|||
->where('attribute_code', 'media_gallery')
|
||||
->value('attribute_id');
|
||||
|
||||
if (!$m1MediaGalleryAttrId) {
|
||||
// Media gallery attribute doesn't exist in M1, skip
|
||||
return;
|
||||
}
|
||||
|
||||
// Get media_gallery attribute ID from M2
|
||||
$m2EntityTypeId = DB::connection($this->magento2Connection)
|
||||
->table($this->magento2Prefix . 'eav_entity_type')
|
||||
|
|
@ -2554,44 +2551,144 @@ protected function migrateProductMediaGallery($m1ProductId, $m2ProductId, $m1Ent
|
|||
|
||||
$images = [];
|
||||
|
||||
// Also check for individual image attributes (image, small_image, thumbnail)
|
||||
// These are stored as separate varchar attributes in M1
|
||||
$imageAttributes = ['image', 'small_image', 'thumbnail'];
|
||||
$m1ImageAttributeIds = [];
|
||||
foreach ($imageAttributes as $attrCode) {
|
||||
$attrId = DB::connection($this->magento1Connection)
|
||||
->table($this->magento1Prefix . 'eav_attribute')
|
||||
->where('entity_type_id', $m1EntityTypeId)
|
||||
->where('attribute_code', $attrCode)
|
||||
->value('attribute_id');
|
||||
if ($attrId) {
|
||||
$m1ImageAttributeIds[$attrCode] = $attrId;
|
||||
}
|
||||
}
|
||||
|
||||
// Get individual image attribute values from M1
|
||||
if (!empty($m1ImageAttributeIds)) {
|
||||
$m1ImageValues = DB::connection($this->magento1Connection)
|
||||
->table($this->magento1Prefix . 'catalog_product_entity_varchar')
|
||||
->where('entity_id', $m1ProductId)
|
||||
->whereIn('attribute_id', array_values($m1ImageAttributeIds))
|
||||
->where('store_id', 0)
|
||||
->whereNotNull('value')
|
||||
->where('value', '!=', '')
|
||||
->where('value', '!=', 'no_selection')
|
||||
->get();
|
||||
|
||||
foreach ($m1ImageValues as $imageValue) {
|
||||
$imageFile = $imageValue->value;
|
||||
if (!empty($imageFile)) {
|
||||
// Find which attribute this is
|
||||
$attrCode = array_search($imageValue->attribute_id, $m1ImageAttributeIds);
|
||||
// Add to images array if not already present
|
||||
$found = false;
|
||||
foreach ($images as $existingImage) {
|
||||
if (isset($existingImage['file']) && $existingImage['file'] === $imageFile) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
$images[] = [
|
||||
'file' => $imageFile,
|
||||
'label' => ucfirst($attrCode ?? 'Image'),
|
||||
'position' => count($images) + 1,
|
||||
'disabled' => 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// First, try to get images from M1 media gallery tables (if they exist)
|
||||
// In M1, catalog_product_entity_media_gallery has: value_id, attribute_id, entity_id, value
|
||||
try {
|
||||
$m1MediaGalleryTable = $this->magento1Prefix . 'catalog_product_entity_media_gallery';
|
||||
$m1MediaGalleryValueTable = $this->magento1Prefix . 'catalog_product_entity_media_gallery_value';
|
||||
|
||||
// Check if M1 media gallery tables exist
|
||||
$m1GalleryImages = DB::connection($this->magento1Connection)
|
||||
// Check if M1 media gallery tables exist by trying to query them
|
||||
// Filter by entity_id (product ID) - this is the key field
|
||||
$m1GalleryQuery = DB::connection($this->magento1Connection)
|
||||
->table($m1MediaGalleryTable)
|
||||
->where('entity_id', $m1ProductId)
|
||||
->get();
|
||||
->where('entity_id', $m1ProductId);
|
||||
|
||||
// Some M1 versions have attribute_id in the media_gallery table, try to filter by it if it exists
|
||||
// But don't fail if the column doesn't exist
|
||||
try {
|
||||
if ($m1MediaGalleryAttrId) {
|
||||
$m1GalleryQuery->where('attribute_id', $m1MediaGalleryAttrId);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// attribute_id column might not exist, continue without it
|
||||
Log::debug("attribute_id column not found in M1 media gallery table, using entity_id only");
|
||||
}
|
||||
|
||||
$m1GalleryImages = $m1GalleryQuery->get();
|
||||
|
||||
Log::info("Found " . $m1GalleryImages->count() . " images in M1 media gallery table for product ID {$m1ProductId} (SKU mapping: M1 ID {$m1ProductId} -> M2 ID {$m2ProductId})");
|
||||
|
||||
if ($m1GalleryImages->isNotEmpty()) {
|
||||
// M1 has media gallery tables, use them
|
||||
Log::info("Processing " . $m1GalleryImages->count() . " images from M1 media gallery table");
|
||||
foreach ($m1GalleryImages as $m1Image) {
|
||||
$valueId = $m1Image->value_id;
|
||||
|
||||
// Get value data
|
||||
// Get value data (label, position, disabled) from the value table
|
||||
$m1Value = null;
|
||||
try {
|
||||
$m1Value = DB::connection($this->magento1Connection)
|
||||
->table($m1MediaGalleryValueTable)
|
||||
->where('value_id', $valueId)
|
||||
->where('store_id', 0)
|
||||
->first();
|
||||
} catch (Exception $e) {
|
||||
// Value table might not exist or have different structure
|
||||
Log::debug("Could not read from M1 media gallery value table: " . $e->getMessage());
|
||||
}
|
||||
|
||||
$imageFile = $m1Image->value ?? null;
|
||||
if (empty($imageFile)) {
|
||||
Log::warning("Image file is empty for value_id {$valueId} in M1 product {$m1ProductId}");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if this image is already in the array (from individual attributes)
|
||||
$found = false;
|
||||
foreach ($images as $key => $existingImage) {
|
||||
if (isset($existingImage['file']) && $existingImage['file'] === $imageFile) {
|
||||
$found = true;
|
||||
// Update with gallery data if it has better info
|
||||
if ($m1Value && ($m1Value->label || $m1Value->position > 0)) {
|
||||
$images[$key]['label'] = $m1Value->label ?? $images[$key]['label'];
|
||||
$images[$key]['position'] = $m1Value->position ?? $images[$key]['position'];
|
||||
$images[$key]['disabled'] = $m1Value->disabled ?? $images[$key]['disabled'];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
$images[] = [
|
||||
'file' => $m1Image->value,
|
||||
'file' => $imageFile,
|
||||
'label' => $m1Value->label ?? null,
|
||||
'position' => $m1Value->position ?? 0,
|
||||
'disabled' => $m1Value->disabled ?? 0,
|
||||
];
|
||||
Log::debug("Added image from M1 media gallery: {$imageFile}");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log::debug("No images found in M1 media gallery table for product ID {$m1ProductId}");
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// M1 media gallery tables don't exist, fall back to varchar table
|
||||
Log::debug("M1 media gallery tables not found, using varchar table: " . $e->getMessage());
|
||||
Log::warning("M1 media gallery tables not found or error accessing them, will try varchar table: " . $e->getMessage());
|
||||
}
|
||||
|
||||
// If no images from gallery tables, try varchar table (serialized data)
|
||||
if (empty($images)) {
|
||||
if (empty($images) && $m1MediaGalleryAttrId) {
|
||||
$m1MediaGalleryData = DB::connection($this->magento1Connection)
|
||||
->table($this->magento1Prefix . 'catalog_product_entity_varchar')
|
||||
->where('entity_id', $m1ProductId)
|
||||
|
|
@ -2600,9 +2697,11 @@ protected function migrateProductMediaGallery($m1ProductId, $m2ProductId, $m1Ent
|
|||
->value('value');
|
||||
|
||||
if (empty($m1MediaGalleryData)) {
|
||||
// No media gallery data in M1, skip
|
||||
// No media gallery data in M1, but we might have individual images already
|
||||
if (empty($images)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the media gallery data (Magento 1 stores it as serialized PHP)
|
||||
if (is_string($m1MediaGalleryData)) {
|
||||
|
|
@ -2632,11 +2731,28 @@ protected function migrateProductMediaGallery($m1ProductId, $m2ProductId, $m1Ent
|
|||
}
|
||||
|
||||
foreach ($parsedImages as $img) {
|
||||
$imageFile = null;
|
||||
if (is_string($img)) {
|
||||
$images[] = ['file' => $img];
|
||||
$imageFile = $img;
|
||||
} elseif (is_array($img)) {
|
||||
$imageFile = $img['file'] ?? $img['value'] ?? null;
|
||||
}
|
||||
|
||||
if (!empty($imageFile)) {
|
||||
// Check if this image is already in the array
|
||||
$found = false;
|
||||
foreach ($images as $existingImage) {
|
||||
if (isset($existingImage['file']) && $existingImage['file'] === $imageFile) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
if (is_string($img)) {
|
||||
$images[] = ['file' => $imageFile];
|
||||
} elseif (is_array($img)) {
|
||||
$images[] = [
|
||||
'file' => $img['file'] ?? $img['value'] ?? null,
|
||||
'file' => $imageFile,
|
||||
'label' => $img['label'] ?? $img['label_default'] ?? null,
|
||||
'position' => isset($img['position']) ? (int)$img['position'] : 0,
|
||||
'disabled' => isset($img['disabled']) ? (int)$img['disabled'] : 0,
|
||||
|
|
@ -2646,11 +2762,16 @@ protected function migrateProductMediaGallery($m1ProductId, $m2ProductId, $m1Ent
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($images)) {
|
||||
Log::debug("No images found for product M1 ID {$m1ProductId} -> M2 ID {$m2ProductId}");
|
||||
return;
|
||||
}
|
||||
|
||||
Log::info("Migrating " . count($images) . " images for product M1 ID {$m1ProductId} -> M2 ID {$m2ProductId}");
|
||||
|
||||
// Process each image
|
||||
foreach ($images as $imageData) {
|
||||
// Handle different data structures
|
||||
|
|
@ -2714,13 +2835,18 @@ protected function migrateProductMediaGallery($m1ProductId, $m2ProductId, $m1Ent
|
|||
'value_id' => $valueId,
|
||||
'entity_id' => $m2ProductId,
|
||||
]);
|
||||
Log::debug("Linked image {$imageFile} (value_id: {$valueId}) to M2 product ID {$m2ProductId}");
|
||||
} else {
|
||||
Log::debug("Image {$imageFile} (value_id: {$valueId}) already linked to M2 product ID {$m2ProductId}");
|
||||
}
|
||||
|
||||
// Insert/update catalog_product_entity_media_gallery_value for default store (store_id = 0)
|
||||
// Note: This table requires entity_id as it has a foreign key constraint
|
||||
$valueExists = DB::connection($this->magento2Connection)
|
||||
->table($this->magento2Prefix . 'catalog_product_entity_media_gallery_value')
|
||||
->where('value_id', $valueId)
|
||||
->where('store_id', 0)
|
||||
->where('entity_id', $m2ProductId)
|
||||
->exists();
|
||||
|
||||
if (!$valueExists) {
|
||||
|
|
@ -2729,21 +2855,25 @@ protected function migrateProductMediaGallery($m1ProductId, $m2ProductId, $m1Ent
|
|||
->insert([
|
||||
'value_id' => $valueId,
|
||||
'store_id' => 0,
|
||||
'entity_id' => $m2ProductId,
|
||||
'label' => $label,
|
||||
'position' => $position,
|
||||
'disabled' => $disabled,
|
||||
]);
|
||||
Log::debug("Inserted media gallery value for image {$imageFile} (value_id: {$valueId}, entity_id: {$m2ProductId})");
|
||||
} else {
|
||||
// Update existing value
|
||||
DB::connection($this->magento2Connection)
|
||||
->table($this->magento2Prefix . 'catalog_product_entity_media_gallery_value')
|
||||
->where('value_id', $valueId)
|
||||
->where('store_id', 0)
|
||||
->where('entity_id', $m2ProductId)
|
||||
->update([
|
||||
'label' => $label,
|
||||
'position' => $position,
|
||||
'disabled' => $disabled,
|
||||
]);
|
||||
Log::debug("Updated media gallery value for image {$imageFile} (value_id: {$valueId}, entity_id: {$m2ProductId})");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,15 +18,41 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
});
|
||||
|
||||
function startProductMigration(dryRun) {
|
||||
// Check if routes are available
|
||||
if (!routes || !routes.migrateProducts) {
|
||||
console.error('Product routes not available', routes);
|
||||
alert('Error: Routes not initialized. Please refresh the page.');
|
||||
return;
|
||||
}
|
||||
|
||||
const button = dryRun ? document.getElementById('dryRunProductMigrationBtn') : document.getElementById('startProductMigrationBtn');
|
||||
const otherButton = dryRun ? document.getElementById('startProductMigrationBtn') : document.getElementById('dryRunProductMigrationBtn');
|
||||
|
||||
if (!button) {
|
||||
console.error('Button not found');
|
||||
alert('Error: Button not found. Please refresh the page.');
|
||||
return;
|
||||
}
|
||||
|
||||
const originalText = button.textContent;
|
||||
button.disabled = true;
|
||||
if (otherButton) {
|
||||
otherButton.disabled = true;
|
||||
}
|
||||
button.textContent = dryRun ? 'Running Dry Run...' : 'Migrating...';
|
||||
button.style.cursor = 'not-allowed';
|
||||
|
||||
const logContent = document.getElementById('productMigrationLogContent');
|
||||
if (!logContent) {
|
||||
console.error('Log content element not found');
|
||||
button.disabled = false;
|
||||
if (otherButton) {
|
||||
otherButton.disabled = false;
|
||||
}
|
||||
button.textContent = originalText;
|
||||
return;
|
||||
}
|
||||
|
||||
logContent.innerHTML = '<div class="log-entry">' + (dryRun ? 'Running dry run...' : 'Starting migration...') + '</div>';
|
||||
|
||||
fetch(routes.migrateProducts, {
|
||||
|
|
|
|||
Loading…
Reference in New Issue