module Scrivito class AttributeDeserializer < Struct.new(:model, :workspace) def deserialize(attribute_value, attribute_definition) case attribute_definition.type when 'binary' then deserialize_binary_value(attribute_value) when 'date' then deserialize_date_value(attribute_value) when 'enum' then deserialize_enum_value(attribute_value, attribute_definition) when 'html' then deserialize_html_value(attribute_value) when 'link' then deserialize_link_value(attribute_value) when 'linklist' then deserialize_linklist_value(attribute_value) when 'multienum' then deserialize_multienum_value(attribute_value, attribute_definition) when 'reference' then deserialize_reference_value(attribute_value) when 'referencelist' then deserialize_referencelist_value(attribute_value) when 'widget' then deserialize_legacy_widget_value(attribute_value, attribute_definition) when 'widgetlist' then deserialize_widgetlist_value(attribute_value, attribute_definition) else attribute_value end end private def deserialize_binary_value(attribute_value) if attribute_value && (id = attribute_value['id']) Binary.new(id, workspace.published?) end end def deserialize_date_value(attribute_value) DateAttribute.parse(attribute_value) if attribute_value end def deserialize_enum_value(attribute_value, attribute_definition) attribute_value if attribute_definition.values.include?(attribute_value) end def deserialize_html_value(attribute_value) StringTagging.tag_as_html(attribute_value) end def deserialize_link_value(attribute_value) return unless attribute_value if attribute_value['destination'] deserialize_internal_link(attribute_value) else deserialize_external_link(attribute_value) end end def deserialize_linklist_value(link_definitions) if link_definitions.present? link_definitions = link_definitions.map(&:with_indifferent_access) object_ids = link_definitions.map { |link_data| link_data[:destination] }.compact.uniq objects = object_ids.empty? ? [] : workspace.objs.find(object_ids) link_definitions.each_with_object([]) do |link_data, links| obj = objects.detect { |o| o && o.id == link_data[:destination] } link = Link.new(link_data.merge(obj: obj)) links << link if link.resolved? end else [] end end def deserialize_multienum_value(attribute_value, attribute_definition) attribute_value & attribute_definition.values end def deserialize_reference_value(attribute_value) workspace.objs.find([attribute_value]).first end def deserialize_referencelist_value(attribute_value) workspace.objs.find(attribute_value).compact end def deserialize_internal_link(attribute_value) Link.new(attribute_value.slice('title', 'query', 'fragment', 'target').symbolize_keys .merge(obj: workspace.objs.find(attribute_value['destination']))) rescue ResourceNotFound end def deserialize_external_link(attribute_value) Link.new(attribute_value.slice('url', 'title', 'target').symbolize_keys) end def deserialize_legacy_widget_value(widget_ids, attribute_definition) if workspace.uses_obj_classes deserialize_widgetlist_value(widget_ids, attribute_definition) end end def deserialize_widgetlist_value(widget_ids, attribute_definition) if widget_ids widget_ids.map { |widget_id| deserialize_widget_value(widget_id, attribute_definition) } else [] end end def deserialize_widget_value(widget_id, attribute_definition) model.widget_from_pool(widget_id).tap do |widget| raise ScrivitoError, "Widget with ID #{widget_id} not found!" unless widget widget.container = model widget.container_attribute_name = attribute_definition.name end end end end