getAllVariants(); if (empty($variants)) { $this->error('Keine Daten von Shopify erhalten (Details im Log).'); return self::FAILURE; } // Deduplizieren: pro Produkttitel nur einmal $shopifyProducts = collect($variants) ->filter(fn($v) => ! empty($v['image_urls'])) ->keyBy('product_title'); $totalInShopify = collect($variants)->pluck('product_title')->unique()->count(); $this->info("Shopify-Produkte gesamt: {$totalInShopify}"); $this->info("Davon mit Bild-URLs: {$shopifyProducts->count()}"); if ($shopifyProducts->isEmpty()) { $this->warn('Kein Shopify-Produkt hat Bild-URLs — Import nicht möglich.'); return self::SUCCESS; } $downloaded = 0; $skipped = 0; $notFound = 0; foreach ($shopifyProducts as $title => $variant) { $product = Product::where('title', $title)->first(); if (! $product) { $this->warn(" Nicht lokal gefunden: \"{$title}\""); $notFound++; continue; } if (! empty($product->images) && ! $this->option('force')) { $skipped++; continue; } $paths = []; foreach ($variant['image_urls'] as $url) { try { $response = Http::timeout(30)->get($url); } catch (\Exception $e) { $this->warn(" Verbindungsfehler für {$url}: {$e->getMessage()}"); continue; } if ($response->failed()) { $this->warn(" HTTP {$response->status()} für: {$url}"); continue; } $body = $response->body(); if (empty($body)) { $this->warn(" Leere Antwort für: {$url}"); continue; } $ext = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION) ?: 'jpg'; $filename = 'product-images/' . Str::uuid() . '.' . $ext; Storage::disk('public')->put($filename, $body); $paths[] = $filename; } if (! empty($paths)) { $product->update(['images' => $paths]); $this->line(" ✓ {$title} (" . count($paths) . " Bild(er))"); $downloaded++; } else { $this->warn(" Keine Bilder gespeichert für: \"{$title}\""); } } $this->info("✓ {$downloaded} Produkte mit Bildern versorgt"); if ($skipped) { $this->line(" {$skipped} übersprungen (haben bereits Bilder — nutze --force zum Überschreiben)"); } if ($notFound) { $this->warn(" {$notFound} Shopify-Produkte lokal nicht gefunden (Titelabweichung?)"); } return self::SUCCESS; } }