lib/scrivito/basic_obj.rb in scrivito_sdk-0.17.0 vs lib/scrivito/basic_obj.rb in scrivito_sdk-0.18.0

- old
+ new

@@ -4,10 +4,24 @@ module Scrivito # The CMS file class # @api public class BasicObj + UNIQ_ATTRIBUTES = %w[ + _id + _path + _permalink + ].freeze + + GENERATED_ATTRIBUTES = %w[ + _conflicts + _last_changed + _modification + _obj_type + _text_links + ].freeze + extend ActiveModel::Naming include AttributeContent include ModelIdentity @@ -75,14 +89,13 @@ # @param [Hash] attributes # @return [Obj] the newly created {BasicObj Obj} def self.create(attributes) attributes = with_default_obj_class(attributes) api_attributes, widget_properties = prepare_attributes_for_rest_api(attributes, nil) - json = CmsRestApi.post(cms_rest_api_path, obj: api_attributes) - obj = find(json['id'] || json['_id']) + json = Workspace.current.api_request(:post, '/objs', obj: api_attributes) + obj = find(json['_id']) CmsRestApi::WidgetExtractor.notify_persisted_widgets(obj, widget_properties) - Workspace.current.reload obj end # Create a new {BasicObj Obj} instance with the given values and attributes. # Normally this method should not be used. @@ -261,27 +274,40 @@ # } # } # ) def update(attributes) api_attributes, widget_properties = prepare_attributes_for_rest_api(attributes) - CmsRestApi.put(cms_rest_api_path, obj: api_attributes) - workspace.reload - reload + workspace.api_request(:put, "/objs/#{id}", obj: api_attributes) + reload_data CmsRestApi::WidgetExtractor.notify_persisted_widgets(self, widget_properties) self end + # Copies itself to a given path. + # @api public + # @param [Hash] options + # @option options [String,Symbol] :_path (nil) the path of the copy. + # @option options [String,Symbol] :_id (nil) the id of the copy. + # @option options [String,Symbol] :_permalink (nil) the permalink of the copy. + # @raise [ArgumentError] if +options+ includes invalid keys. + # @return [Obj] the created copy + # @example Copy a blog post. + # blog_post = Obj.find_by_path('/blog/first_post') + # blog_post.copy(_path: '/blog/second_post') + def copy(options) + options = options.stringify_keys.assert_valid_keys('_path', '_id', '_permalink') + json = workspace.api_request(:post, '/objs', obj: copyable_attributes.merge(options)) + self.class.find(json['_id']) + end + # Destroys the {BasicObj Obj} in the current {Workspace} # @api public def destroy if children.any? raise ClientError.new(I18n.t('scrivito.errors.models.basic_obj.has_children'), 412) end - - CmsRestApi.delete(cms_rest_api_path) - - workspace.reload + workspace.api_request(:delete, "/objs/#{id}") end def to_param id end @@ -484,33 +510,22 @@ # Reloads the attributes of this object from the database. # Notice that the ruby class of this Obj instance will NOT change, # even if the obj_class in the database has changed. # @api public def reload - id = self.id.to_s + workspace.reload + reload_data + end - reload_data = Proc.new do + def reload_data + id = self.id.to_s + update_data -> { CmsBackend.instance.find_obj_data_by(workspace.revision, :id, [id]).first.first - end - - update_data(reload_data) + } end - # @return [String] # @api public - def obj_class_name - read_attribute('_obj_class') - end - - # Returns the {Scrivito::ObjClass} of this object. - # @return [Scrivito::ObjClass] - # @api public - def obj_class - ObjClass.find(obj_class_name) - end - - # @api public def last_changed read_attribute('_last_changed') end def new?(revision=Workspace.current.base_revision) @@ -663,39 +678,27 @@ # Reverts changes of this object. # After calling this method it's as if this object has been never modified in the current working copy. # This method does not work with +new+ or +deleted+ objects. # This method also does also not work for the +published+ workspace or the +rtc+ working copy. def revert - workspace.assert_revertable + assert_revertable - if binary? - raise "revert not supported for binary objs" - else - case modification - when Modification::UNMODIFIED - # don't do anything - when Modification::EDITED - previous_content = CmsRestApi.get( - "revisions/#{workspace.base_revision_id}/objs/#{id}") - updated_content = previous_content.except('id', '_id') + if modification == Modification::EDITED + base_revision_path = "revisions/#{workspace.base_revision_id}/objs/#{id}" + previous_attributes = CmsRestApi.get(base_revision_path).except('_id') + previous_widget_pool = previous_attributes['_widget_pool'] - added_widget_ids = read_widget_pool.keys - previous_content['_widget_pool'].keys - added_widget_ids.each do |added_widget_id| - updated_content['_widget_pool'][added_widget_id] = nil - end + ids_of_new_widgets = read_widget_pool.keys - previous_widget_pool.keys + ids_of_new_widgets.each { |widget_id| previous_widget_pool[widget_id] = nil } - CmsRestApi.put(cms_rest_api_path, obj: updated_content) - - reload - else - raise ScrivitoError, "cannot revert changes, since obj is #{modification}." - end + workspace.api_request(:put, "/objs/#{id}", obj: previous_attributes) + reload end end def mark_resolved - CmsRestApi.put(cms_rest_api_path, obj: {_conflicts: nil}) + workspace.api_request(:put, "/objs/#{id}", obj: {_conflicts: nil}) reload end def container_and_field_name_for_widget(widget_id) if field_name = field_name_in_data_for_widget(data_from_cms, widget_id) @@ -716,10 +719,14 @@ def has_conflict? read_attribute('_conflicts') != nil end + def publishable? + !has_conflict? + end + def all_widgets_from_pool read_widget_pool.keys.map do |widget_id| widget_from_pool(widget_id) end end @@ -732,10 +739,28 @@ end raise ScrivitoError.new('Could not generate a new unused widget id') end + # Generates a +Hash+ containing all public attributes. The hash will _not_ include attributes, + # which are read-only or used for internal purpose. + # @api public + # @return [Hash] a hash containing all public attributes. + # @example + # old_obj = Obj.homepage + # attrs = old_obj.to_h + # puts attrs + # #=> {"_obj_class"=>"Publication", "_path"=>"/", "_id"=>"f64a68258ca15faf", "_widget_pool"=>{}} + # old_obj.destroy + # + # new_obj = Obj.create(attrs) + # puts new_obj == old_obj + # #=> true + def to_h + data_from_cms.to_h.except(*GENERATED_ATTRIBUTES) + end + private def cms_data_for_revision(revision) if revision CmsBackend.instance.find_obj_data_by(revision, "id", [id]).first.first @@ -772,14 +797,10 @@ def find_blob blob_spec = read_attribute('blob') Blob.find(blob_spec["id"]) if blob_spec end - def cms_rest_api_path(obj_id = id) - "#{self.class.cms_rest_api_path(workspace)}/#{obj_id}" - end - def workspace if revision.workspace revision.workspace else raise ScrivitoError, "No workspace set for this obj" @@ -792,20 +813,29 @@ def prepare_attributes_for_rest_api(attributes) self.class.prepare_attributes_for_rest_api(attributes, self) end + def copyable_attributes + workspace.api_request(:get, "/objs/#{id}") + .except(*GENERATED_ATTRIBUTES) + .except(*UNIQ_ATTRIBUTES) + end + + def assert_revertable + workspace.assert_revertable + raise "revert not supported for binary objs" if binary? + if modification == Modification::NEW || modification == Modification::DELETED + raise ScrivitoError, "cannot revert changes, since obj is #{modification}." + end + end + class << self def restore(obj_id) Workspace.current.assert_revertable - base_revision_path = "revisions/#{Workspace.current.base_revision_id}/objs/#{obj_id}" - obj_attributes = CmsRestApi.get(base_revision_path).except('id').merge('_id' => obj_id) - CmsRestApi.post(cms_rest_api_path, obj: obj_attributes) - end - - def cms_rest_api_path(workspace = Workspace.current) - "workspaces/#{workspace.id}/objs" + obj_attributes = CmsRestApi.get(base_revision_path).merge('_id' => obj_id) + Workspace.current.api_request(:post, '/objs', obj: obj_attributes) end def prepare_attributes_for_rest_api(attributes, obj) widget_properties = CmsRestApi::WidgetExtractor.call(attributes, obj) api_attributes = CmsRestApi::AttributeSerializer.convert(attributes)