#require 'fiona7/write_obj' #require 'fiona7/released_obj' #require 'fiona7/edited_obj' require 'fiona7/builder/obj_builder' require 'fiona7/builder/obj_updater' require 'fiona7/naive_search_engine' require 'fiona7/verity_search_engine' require 'fiona7/assert' require 'fiona7/json/reverse_obj_decorator' require 'fiona7/json/typeless_obj_decorator' module Fiona7 module Controllers module RestAPI class ObjController def create(workspace_id, values) assert_writable(workspace_id) # some stupid creators give us an id. fck them values[:obj].delete("_id") values[:obj].delete(:_id) # This is a hack to make it seem as if the root obj does not exist if values[:obj][:_path] != '/' && values[:obj]["_path"] != '/' obj = Builder::ObjBuilder.new(values[:obj].dup).build else obj = Builder::ObjUpdater.new(values[:obj].merge(_id: 2001)).build end klass = EditedObj decorated = Fiona7::JSON::ReverseObjDecorator.new(klass, obj) return ::JSON.parse(::ActiveSupport::JSON.encode(decorated)) end def fetch_by_path(workspace_id, path) klass = matching_class(workspace_id) path = path.gsub('.', '_') obj = klass.find_by_path(path) Assert.input( !obj.nil?, "Obj with path #{path} not found in workspace #{workspace_id}", 404 ) decorated = Fiona7::JSON::ReverseObjDecorator.new(klass, obj) return ::JSON.parse(::ActiveSupport::JSON.encode(decorated)) end def fetch_by_id(workspace_id, obj_id) klass = matching_class(workspace_id) obj = klass.where(obj_id: obj_id).first Assert.input( !obj.nil?, "Obj with id #{obj_id} not found in workspace #{workspace_id}", 404 ) decorated = Fiona7::JSON::ReverseObjDecorator.new(klass, obj) response = ::JSON.parse(::ActiveSupport::JSON.encode(decorated)) return response end def fetch_by_id_from_revision(revision_id, obj_id) # TODO: use implementation from ContentService controller # FIXME: code duplication with fetch_by_id klass = revision_id.start_with?('f') ? ReleasedObj : EditedObj obj = klass.where(obj_id: obj_id).first Assert.input( !obj.nil?, "Obj with id #{obj_id} not found in revision #{revision_id}", 404 ) decorated = Fiona7::JSON::ReverseObjDecorator.new(klass, obj) return ::JSON.parse(::ActiveSupport::JSON.encode(decorated)) end def search(workspace_id, params) klass = matching_class(workspace_id) if params[:query].blank? return ::JSON.parse(::ActiveSupport::JSON.encode({ total: 0, results: [] })) end offset = params[:offset] || 0 size = params[:size] || 100 query = (params[:query] || []).dup order = (params[:sort_order] || :asc).to_sym sort = (params[:sort_by] || :id).to_sym #puts "SEARCH: #{query}" if use_naive_search_engine?(query) #puts "NAIVE" search = NaiveSearchEngine.new(klass, query, offset, size, sort, order) else #puts "VERITY" search = VeritySearchEngine.new(klass, query, offset, size, sort, order) end result = search.results.map {|o| {id: o.id} } total = search.total return ::JSON.parse(::ActiveSupport::JSON.encode({ total: total, results: result })) end def update(workspace_id, values) assert_writable(workspace_id) obj = Builder::ObjUpdater.new(values[:obj].dup.with_indifferent_access).build klass = EditedObj decorated = Fiona7::JSON::ReverseObjDecorator.new(klass, obj) return ::JSON.parse(::ActiveSupport::JSON.encode(decorated)) end def destroy(workspace_id, obj_id) # TODO: cleanup /_widgets and /_uploads obj = WriteObj.find(obj_id) if !obj.children.empty? if obj.children.all? {|c| c.name == '_widgets' || c.name == '_uploads' } remove_obj_tree(obj) else Assert.input( false, "Cannot remove object #{obj_id} because it has children objects" ) end else obj.destroy end return {} end protected def remove_obj_tree(rc_obj) subtree_objects = WriteObj.where(["path like ?", "#{rc_obj.path}/%"]) tree = ([rc_obj] + subtree_objects).sort_by{|obj| obj.path}.reverse outside_objects = [] tree.each do |obj| obj.super_objects.each do |super_object| if !super_object.path.start_with?(rc_obj.path) outside_objects << super_object end end end if outside_objects.length != 0 outsize_paths = outsize_objects.map(&:path).join(" ") Assert.input( false, "Cannot remove object because #{outside_paths} have links pointing to it" ) end tree.each do |obj| obj.send(:crul_obj).remove_archived_contents! obj.send(:crul_obj).remove_active_contents! end tree.each do |obj| obj.send(:crul_obj).delete! end end def matching_class(workspace_id) workspace_id = workspace_id.to_sym Assert.input( workspace_id == :rtc || workspace_id == :published, "Workspace #{workspace_id} not found" ) klass = workspace_id == :published ? ReleasedObj : EditedObj end def assert_writable(workspace_id) workspace_id = workspace_id.to_sym Assert.input( workspace_id == :rtc, "Workspace #{workspace_id} is not writable, only workspace rtc is writable" ) end def use_naive_search_engine?(query) false || query.empty? || query.any? {|q| q[:field].to_sym == :_path && (q[:operator].to_sym == :equal || query.length == 1)} || (query.length == 1 && query.first[:field].to_sym == :_modification) || (query.length == 1 && query.first[:field].to_sym == :_obj_class) || (query.length == 1 && query.first[:field].to_sym == :id) || (query.length == 1 && query.first[:field].to_sym == :_permalink) || false end end end end end