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