From 662b9174fa113fff5ad6d3aa0c6de5d7f14a1429 Mon Sep 17 00:00:00 2001 From: Martin Artnik Date: Thu, 12 Jan 2023 13:24:31 +0100 Subject: [PATCH] Extract pasted base64 images from RTE texts [SCI-5098] --- app/models/concerns/tiny_mce_images.rb | 38 ++++++++++++++++++++++++++ app/models/step.rb | 1 - app/models/tiny_mce_asset.rb | 9 +++++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/app/models/concerns/tiny_mce_images.rb b/app/models/concerns/tiny_mce_images.rb index af668b27e..f2958dcfb 100644 --- a/app/models/concerns/tiny_mce_images.rb +++ b/app/models/concerns/tiny_mce_images.rb @@ -10,6 +10,7 @@ module TinyMceImages dependent: :destroy before_save :clean_tiny_mce_image_urls + before_save :extract_base64_images def prepare_for_report(field, base64_encoded_imgs = false) description = self[field] @@ -162,5 +163,42 @@ module TinyMceImages end self[object_field] = parsed_description.to_html if image_changed end + + def extract_base64_images + # extracts and uploads any base64 encoded images, + # so they get stored as files instead of directly in the text + + object_field = Extends::RICH_TEXT_FIELD_MAPPINGS[self.class.name] + + text = public_send(object_field) + + return unless text + + ActiveRecord::Base.transaction do + text.scan(/src="(data:image\/[^;]+;base64[^"]+)"/i).flatten.each do |base64_src| + base64_data = base64_src.split('base64,').last + + tiny_image = TinyMceAsset.create!( + team: @team, + object: self, + saved: true + ) + + tiny_image.image.attach( + io: StringIO.new(Base64.decode64(base64_data)), + filename: SecureRandom.hex(32) + ) + + encoded_id = Base62.encode(tiny_image.id) + + text.gsub!( + "#{base64_src}\"", + "\" data-mce-token=\"#{encoded_id}\" alt=\"description-#{encoded_id}\"" + ) + end + + assign_attributes(object_field => text) + end + end end end diff --git a/app/models/step.rb b/app/models/step.rb index 856537dbe..4ce6f7bc7 100644 --- a/app/models/step.rb +++ b/app/models/step.rb @@ -1,7 +1,6 @@ class Step < ApplicationRecord include SearchableModel include SearchableByNameModel - include TinyMceImages include ViewableModel attr_accessor :skip_position_adjust # to be used in bulk deletion diff --git a/app/models/tiny_mce_asset.rb b/app/models/tiny_mce_asset.rb index 4db7cce12..fbd699bac 100644 --- a/app/models/tiny_mce_asset.rb +++ b/app/models/tiny_mce_asset.rb @@ -21,7 +21,14 @@ class TinyMceAsset < ApplicationRecord validates :estimated_size, presence: true def self.update_images(object, images, current_user) - images = JSON.parse(images) + # image ids that are present in text + text_images = + object.public_send(Extends::RICH_TEXT_FIELD_MAPPINGS[self.class.name]) + .scan(/data-mce-token="([^"]+)"/) + .flatten + + images = JSON.parse(images) + text_images + current_images = object.tiny_mce_assets.pluck(:id) images_to_delete = current_images.reject do |x| (images.include? Base62.encode(x))