From 4c086e3d407f1462b0d9cd437e080d9372bab100 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Thu, 13 Feb 2025 16:50:22 +1100 Subject: [PATCH] Update images in DFC product import on URL change --- .../app/services/image_builder.rb | 16 ++++++++- .../app/services/product_group_builder.rb | 4 +++ .../spec/services/image_builder_spec.rb | 21 ++++++++++++ .../supplied_product_importer_spec.rb | 33 +++++++++++++++++++ 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 engines/dfc_provider/spec/services/image_builder_spec.rb diff --git a/engines/dfc_provider/app/services/image_builder.rb b/engines/dfc_provider/app/services/image_builder.rb index df6141ce07..06ab056e0c 100644 --- a/engines/dfc_provider/app/services/image_builder.rb +++ b/engines/dfc_provider/app/services/image_builder.rb @@ -4,13 +4,27 @@ require "private_address_check" require "private_address_check/tcpsocket_ext" class ImageBuilder < DfcBuilder + def self.apply(image_url, spree_product) + return if image_url.blank? + + return if image_url == current_image_url(spree_product) + + image = ImageBuilder.import(image_url) + spree_product.image = image if image + end + + def self.current_image_url(spree_product) + spree_product.image&.attachment&.blob&.custom_metadata&.fetch("origin", nil) + end + def self.import(image_link) url = URI.parse(image_link) filename = File.basename(image_link) + metadata = { custom: { origin: image_link } } Spree::Image.new.tap do |image| PrivateAddressCheck.only_public_connections do - image.attachment.attach(io: url.open, filename:) + image.attachment.attach(io: url.open, filename:, metadata:) end end rescue StandardError diff --git a/engines/dfc_provider/app/services/product_group_builder.rb b/engines/dfc_provider/app/services/product_group_builder.rb index c8c8e6f62d..cfaa58dd4a 100644 --- a/engines/dfc_provider/app/services/product_group_builder.rb +++ b/engines/dfc_provider/app/services/product_group_builder.rb @@ -17,7 +17,11 @@ class ProductGroupBuilder < DfcBuilder description = supplied_product.isVariantOf.first.try(:description) || supplied_product.description name = supplied_product.isVariantOf.first.try(:name) + image_url = supplied_product.isVariantOf.first.try(:image) || + supplied_product.image + spree_product.description = description if description.present? spree_product.name = name if name.present? + ImageBuilder.apply(image_url, spree_product) end end diff --git a/engines/dfc_provider/spec/services/image_builder_spec.rb b/engines/dfc_provider/spec/services/image_builder_spec.rb new file mode 100644 index 0000000000..e1e353edfe --- /dev/null +++ b/engines/dfc_provider/spec/services/image_builder_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require_relative "../spec_helper" + +RSpec.describe ImageBuilder do + include FileHelper + + let(:url) { "https://example.net/image.png" } + + before do + stub_request(:get, url).to_return(status: 200, body: black_logo_path.read) + end + + describe ".import" do + it "downloads an image" do + image = ImageBuilder.import(url) + expect(image).to be_a Spree::Image + expect(image.attachment.blob.custom_metadata["origin"]).to eq url + end + end +end diff --git a/engines/dfc_provider/spec/services/supplied_product_importer_spec.rb b/engines/dfc_provider/spec/services/supplied_product_importer_spec.rb index d344f1653b..b407a4c132 100644 --- a/engines/dfc_provider/spec/services/supplied_product_importer_spec.rb +++ b/engines/dfc_provider/spec/services/supplied_product_importer_spec.rb @@ -227,6 +227,39 @@ RSpec.describe SuppliedProductImporter do expect(imported_product.description).to eq "Choose a variety." end + it "updates images when their URL changes" do + stub_request(:get, "https://cd.net/tomato.png?v=1").to_return( + status: 200, body: black_logo_path.read, + ) + stub_request(:get, "https://cd.net/tomato.png?v=2").to_return( + status: 200, body: white_logo_path.read, + ) + + tomatoes = DfcProvider::SuppliedProduct.new( + "some-id", name: "Tomatoes", + image: "https://cd.net/tomato.png?v=1", + ) + supplied_product.isVariantOf << tomatoes + + imported_product = importer.import_variant(supplied_product, supplier).product + expect(imported_product.image.attachment.filename).to eq "tomato.png?v=1" + + expect { + importer.import_variant(supplied_product, supplier).product + imported_product.reload + } + .not_to change { imported_product.image } + + expect { + tomatoes.image = "https://cd.net/tomato.png?v=2" + importer.import_variant(supplied_product, supplier).product + imported_product.reload + } + .to change { imported_product.image } + + expect(imported_product.image.attachment.filename).to eq "tomato.png?v=2" + end + context "when spree_product_uri doesn't match the server host" do let(:supplied_product) do DfcProvider::SuppliedProduct.new(