lib/fiona7/builder/obj_builder.rb in infopark_fiona7-0.30.0.2 vs lib/fiona7/builder/obj_builder.rb in infopark_fiona7-0.70.0.1

- old
+ new

@@ -3,11 +3,11 @@ class ObjBuilder end end end -require 'fiona7/type_register_mixin' +require 'fiona7/type_register' require 'fiona7/recursive_link_resolver' #require 'fiona7/write_obj' #require 'fiona7/released_obj' require 'fiona7/builder/batch_widget_writer' require 'fiona7/link_converter/scrivito_to_fiona' @@ -15,64 +15,66 @@ module Fiona7 module Builder class ObjBuilder - include TypeRegisterMixin def initialize(values) @values = values.symbolize_keys + # garbage + @values.delete(:_modification) + # revert command sends this info. which is silly. + @values.delete(:_last_changed) + puts "CREATING/UPDATING: #{@values.inspect}" end def build assert_valid prepare_object - create_object write_widget_pool - namespace_attributes store_attributes @obj end def validate true end protected + def update? + false + end + def assert_valid validate || (raise Scrivito::ClientError.new(@error_msg || "Invalid input", 422)) end def prepare_object - @path = @values.delete(:_path) + @path = @values.delete(:_path) || generate_orphaned_path @obj_class = @values.delete(:_obj_class) + @real_obj_class = TypeRegister::NameAliaser.new(virtual: @obj_class).real_obj_class @widget_pool = @values.delete(:_widget_pool) @permalink = @values.delete(:_permalink) - if @path - @path = "/#{@path}" unless @path.start_with?('/') - @name, parent_path = name_and_parent_path_from_path(@path) - end + + @path = "/#{@path}" unless @path.start_with?('/') + @name, parent_path = name_and_parent_path_from_path(@path) @parent = ensure_parent_exists(parent_path) if parent_path - end - def namespace_attributes - # nop - end + ensure_obj_class_exists - def create_object # bottom one is faster, but can only work when there are no widgets and no uploads - if (@widget_pool && !@widget_pool.empty?) || (@values.any? {|_, v| v.kind_of?(File) || v.kind_of?(ActionDispatch::Http::UploadedFile) } ) - @obj = WriteObj.create!(name: @name, parent_obj_id: @parent.id, obj_class: @obj_class) + if (@widget_pool && !@widget_pool.empty?) || (@values.any? {|_, (_, v)| v.kind_of?(File) || v.kind_of?(ActionDispatch::Http::UploadedFile) } ) + @obj = WriteObj.create!(name: @name, parent_obj_id: @parent.id, obj_class: @real_obj_class) else - @obj = WriteObj.new(name: @name, parent_obj_id: @parent.id, obj_class: @obj_class) + @obj = WriteObj.create!(name: @name, parent_obj_id: @parent.id, obj_class: @real_obj_class) end end def write_widget_pool - resolver = WidgetResolver.new(@obj[:X_widget_pool]||[]) + resolver = WidgetResolver.new(@obj.attr_values["X_widget_pool"]||[], WriteObj) @id_map = resolver.id_map @widget_path_map = resolver.path_map if @widget_pool && !@widget_pool.empty? @@ -81,30 +83,50 @@ # FIXME: refactor this code if @widgets.pool_changed? # after widget writing this either has new widgets # or some widgets have been removed - @new_widget_pool = @widget_path_map.map do |widget_id, path| - {title: widget_id, destination_object: path} + + @new_widget_pool = @widget_pool.map do |widget_id, definition| + # widget deleted + next if definition.nil? + {title: widget_id, destination_object: @widget_path_map[widget_id]} + end.compact + + # newly added widgets + @widget_path_map.each do |widget_id, path| + next if !@widget_pool[widget_id].nil? + @new_widget_pool << {title: widget_id, destination_object: path} end + end end end def store_attributes - if @obj.obj_class != @obj_class - @obj.obj_class = @obj_class + if @obj.obj_class != @real_obj_class + @obj.obj_class = @real_obj_class @obj.save! @obj.reload end - # TODO: reload into singleton class @obj.send(:reload_attributes) - @values.each do |attribute_name, value| - virtual_name = attribute_name.to_sym - attribute_name = real_name = type_register.real_attribute_name(@obj.obj_class, virtual_name) - virtual_type = type_register.attribute_type(@obj.obj_class, virtual_name) + type_definition = Fiona7::TypeRegister.instance.write(@obj_class) + if type_definition.nil? + raise "Definition not found for #{@obj_class}" + end + @values.each do |attribute_name, possible_pair| + (claimed_type, value) = *possible_pair + attribute = type_definition.find_attribute(attribute_name) + if attribute.nil? + debugger + raise "Attribute #{attribute_name} not found in #{@obj_class}" + end + virtual_name = attribute.name.to_sym + attribute_name = real_name = attribute.real_name.to_sym + virtual_type = attribute.type.to_sym + case virtual_type when :linklist links = (value || []).map do |link| link = link.symbolize_keys new_link = {} @@ -160,56 +182,108 @@ when :referencelist ids = value || [] if ids.empty? @obj.set(attribute_name.to_s, []) else - objects_map = Hash[WriteObj.where(obj_id: ids).map {|o| [o.id, o]}] + objects_map = Hash[WriteObj.where(obj_id: ids).map {|o| [o.id.to_s, o]}] objects = ids.map {|id| objects_map[id] }.compact @obj.set(attribute_name, objects) end - when :widget + when :widgetlist links = [] - value = (value || {}).symbolize_keys - (value[:list] || []).each do |crap| - widget_id = (crap[:widget] || crap['widget']).to_sym - - if (path=@widget_path_map[widget_id]||@widget_path_map[widget_id.to_s]) - links << {destination_object: path, title: widget_id} - else - raise Scrivito::ScrivitoError, "Inconsistent widget pool state detected, unable to store widgets" + if value.kind_of?(Array) + (value || []).each do |widget_id| + if (path=@widget_path_map[widget_id]||@widget_path_map[widget_id.to_s]) + links << {destination_object: path, title: widget_id} + else + raise Scrivito::ScrivitoError, "Inconsistent widget pool state detected, unable to store widgets (unable to find #{widget_id} in #{@widget_path_map.inspect})" + end end + elsif value.kind_of?(Hash) + # stupid shits could not use one consistent format + (value || {})["list"].each do |crap| + widget_id = crap["widget"] + if (path=@widget_path_map[widget_id]||@widget_path_map[widget_id.to_s]) + links << {destination_object: path, title: widget_id} + else + raise Scrivito::ScrivitoError, "Inconsistent widget pool state detected, unable to store widgets (unable to find #{widget_id} in #{@widget_path_map.inspect})" + end + end end @obj.set(attribute_name.to_s, links) when :text, :string, :enum, :multienum, :date + #if value.nil? && value != @obj[attribute_name] @obj.set(attribute_name.to_s, value) + #end + when :stringlist + @obj.set(attribute_name.to_s, value.to_json) when :html converted_links = LinkConverter::ScrivitoToFiona.new(WriteObj, value.to_s).convert @obj.set(attribute_name.to_s, converted_links) when :binary if value.kind_of?(String) # NOTE: this code path has not been tested yet. - target = {title: value, destination_object: ReleasedObj.find(value.to_i)} + target = {title: value, destination_object: InternalReleasedObj.find(value.to_i)} @obj.set(attribute_name.to_s, target) elsif value.kind_of?(File) - @obj.set(attribute_name.to_s, upload_file(value)) + if !Fiona7.mode == :legacy || attribute_name.to_s != "blob" + @obj.set(attribute_name.to_s, upload_file(value)) + else + special_upload_handling(attribute_name, value) + end elsif value.kind_of?(ActionDispatch::Http::UploadedFile) - @obj.set(attribute_name.to_s, upload_uploaded_file(value)) + if !Fiona7.mode == :legacy || attribute_name.to_s != "blob" + @obj.set(attribute_name.to_s, upload_file(value)) + else + special_upload_uploaded_handling(attribute_name, value) + end elsif value.nil? + @obj.set(attribute_name.to_s, []) + elsif value.kind_of?(Hash) + #TODO: legacy mode! + target = {title: value["id"], destination_object: InternalReleasedObj.find(value["id"].to_i)} + @obj.set(attribute_name.to_s, target) else raise Scrivito::ClientError.new("Invalid input for binary field", 422) end else raise Scrivito::ClientError.new("Unknown attribute type: #{virtual_type}", 418) end end @obj.set(:X_widget_pool, @new_widget_pool) if @new_widget_pool @obj.set(:permalink, @permalink) if @permalink + @obj.save! - @obj.edit! unless @obj.really_edited? + #if !@values.empty? || !@new_widget_pool.nil? + @obj.edit! unless @obj.really_edited? + #end end + def special_upload_handling(attribute_name, file) + if !@obj.binary? + # standard handling! + @obj.set(attribute_name.to_s, upload_file(file)) + else + ext = ::File.extname(file.path).to_s[1..-1] + @obj.upload(file, ext) + end + end + + def special_upload_uploaded_handling(attribute_name, file) + if !@obj.binary? + # standard handling! + @obj.set(attribute_name.to_s, upload_uploaded_file(file)) + else + ext = ::File.extname(file.original_filename).to_s[1..-1] + @obj.upload(file.open, ext) + end + end + + + + def upload_file(file) # only publication type can contain children (code = "5") # also handle / this way if @obj.obj_type_code != "5" || @obj.id == 2001 parent_path = "/_uploads/#{@obj.id}" @@ -288,10 +362,24 @@ name, parent_path = name_and_parent_path_from_path(path) WriteObj.create!(name: name, parent_obj_id: WriteObj.find_by_path(parent_path).id, obj_class: 'X_Container') end end - WriteObj.find_by_path(original) + WriteObj.find_by_path(original) || (raise "Tried to make sure that the parent under '#{original}' exist, but it does not :(") + end + + def generate_orphaned_path + return nil if update? + "_orphaned/#{SecureRandom.hex(16)}" + end + + def ensure_obj_class_exists + values = @values.with_indifferent_access + obj_class = @obj_class + + Fiona7::TypeRegister.instance.ad_hoc_synchronize( + Fiona7::TypeRegister::AdHocTypeDefinition.new(values, obj_class).type_definition + ) end end end end