module Scrivito class ObjsController < WebserviceController around_action :require_selected_workspace_write_authorization, only: [ :copy, :create, :destroy, :destroy_widget, :duplicate, :mark_resolved, :restore, :restore_widget, :revert, :revert_widget, :update, ] before_filter :require_identical_selected_and_visible_workspace, only: [ :copy, :create, :duplicate, :page_class_selection, :update, :widget_class_selection, ] def show in_selected_workspace { render } end def widget in_selected_workspace { render } end def create params_parser = ObjCreateParamsParser.new(request.host, request.port) @obj = Obj.create(params_parser.parse(params[:obj]), scrivito_user: scrivito_user) render :obj rescue ObjClassNotFound => e raise ClientError.new( "You've tried to create a CMS object based on the \"#{e.message}\" class, which is "\ "either missing or not suitable for the object.", 400 ) end def details assert_dialog_layout render current_obj.details_view_path, layout: 'scrivito_dialog', formats: :html end def update params_parser = ObjUpdateParamsParser.new(request.host, request.port, current_obj: current_obj, scrivito_user: scrivito_user) current_obj.update(params_parser.parse(params[:obj])) end def destroy in_selected_workspace do parent = current_obj.parent @redirect_to = parent ? scrivito_path(parent) : "/" current_obj.destroy end end def destroy_widget in_selected_workspace { current_widget.destroy } render_empty_json end def revert in_selected_workspace { current_obj.revert } render_empty_json end def revert_widget in_selected_workspace { current_widget.revert } render_empty_json end def restore in_selected_workspace { Obj.restore(params[:id]) } render_empty_json end def restore_widget in_selected_workspace { current_obj.restore_widget(params[:widget_id]) } render_empty_json end def conflicting_workspaces @workspaces = [] render :workspaces end def is_outdated @is_outdated = false end def binary_no_cache in_selected_workspace do binary = current_obj[params[:attribute_name]] @no_cache_url = binary.no_cache_url end end def mark_resolved in_selected_workspace { current_obj.mark_resolved } render_empty_json end def copy @obj = copy_obj(current_obj, params[:parent_path]) render :obj end def transfer_modifications in_selected_workspace do begin obj = Obj.find_including_deleted(params[:id]) workspace = Workspace.find(params[:workspace_id]) authorize_workspace_access(:write, workspace) do obj.transfer_modifications_to(workspace) end rescue TransferModificationsModifiedError @error_reason = :modified rescue TransferModificationsConflictError @error_reason = :conflict end end end def duplicate @obj = copy_obj(current_obj, current_obj.parent_path) render :obj end def page_class_selection @page_class_markup = valid_page_classes.map do |page_class_name| build_selection_option(page_class_name) end end def widget_class_selection load_obj @widgets_classes = valid_widget_classes.map do |widget_class_name| build_selection_option(widget_class_name) end end def search in_selected_workspace do @query = MultiJson.decode(params[:query]).with_indifferent_access @enumerator = ObjSearchBuilder.new(@query).build if params[:query_action] == 'size' return render action: 'search/size' end unless @formatter = fetch_formatter(@query[:format]) return render action: 'search/missing_formatter', status: :not_found end if facet_params = params[:facet] attribute, options = MultiJson.decode(facet_params).values_at('attribute', 'options') @facets = @enumerator.facet(attribute, options || {}) return render action: 'search/facet' end @batch = @enumerator.fetch_batch(params[:continuation]) render :search end end private def require_identical_selected_and_visible_workspace if selected_workspace != editing_context.visible_workspace raise ScrivitoError, 'selected and visible workspace are not identical' end end def require_selected_workspace_write_authorization(&block) authorize_workspace_access(:write, selected_workspace, &block) end def in_selected_workspace(&block) selected_workspace.as_current(&block) end def selected_workspace editing_context.selected_workspace end def current_obj @obj || load_obj end helper_method :current_obj def load_obj @obj = Obj.find(params[:id]) end def current_widget @widget || load_widget end helper_method :current_widget def load_widget raise ScrivitoError, 'no widget_id param specified' if params[:widget_id].blank? unless @widget = current_obj.widget_from_pool(params[:widget_id]) raise ResourceNotFound, "widget with ID '#{params[:widget_id]}' not found" end @widget end def copy_obj(obj, parent_path) id = SecureRandom.hex(8) obj.copy(_id: id, _path: parent_path && "#{parent_path}/#{id}") end def fetch_formatter(name) name ? Configuration.obj_formats[name] : proc { |obj, _| obj.id } end def build_selection_option(class_name) template_path = "#{class_name.underscore}/thumbnail" markup = begin render_to_string(template_path, layout: false, formats: :html) rescue ActionView::MissingTemplate render_to_string('scrivito/fallback_thumbnail', layout: false, formats: :html, locals: {class_name: class_name, template_path: template_path}) end {name: class_name, markup: markup} end def valid_page_classes without_hidden_classes(page_classes_from_obj).map(&:to_s) end def page_classes_from_obj Obj.valid_page_ruby_classes_beneath(params[:parent_path]) end def valid_widget_classes widget_classes = current_widget_or_obj.valid_widget_ruby_classes_for(params[:field_name]) without_hidden_classes(widget_classes).map(&:to_s) end def without_hidden_classes(obj_types) obj_types.reject(&:hide_from_editor?) end def current_widget_or_obj widget_id = params[:widget_id] (widget_id && current_obj.widgets[widget_id]) || current_obj end def assert_dialog_layout view_context.lookup_context.find('layouts/scrivito_dialog') rescue ActionView::MissingTemplate raise %{ Missing the Scrivito dialog layout! Scrivito requires a special view layout in order to render the details dialog. Normally the install generator places it in `app/views/layouts/scrivito_dialog.html.erb`. If upgrading Scrivito, please re-run the install generator: `rails g scrivito:install`. } end end end