module Scrivito # This class represents a CMS obj class. Obj classes can be created, updated and all properties # can be read. The class also provides methods to find obj classes. The attributes of an obj class # are defined by {Scrivito::Attribute} instances. # # @api public class ObjClass include ModelIdentity class << self # Returns all the obj classes. # # @api public # # @example Find all obj classes in the current {Scrivito::Workspace}. # ObjClass.all # # @return [Array] def all results = CmsRestApi.get("workspaces/#{Workspace.current.id}/obj_classes")['results'] results.map do |properties| new(properties) end end # Finds an obj class by its name. # # @api public # # @example Find the obj class named "Homepage" in the current {Scrivito::Workspace}. # ObjClass.find('Homepage') # # @param [String] name The name of the obj class. # @return [Scrivito::ObjClass] # @raise [Scrivito::ResourceNotFound] Raised when no obj class with the given +name+ can be found. def find(name) response = begin CmsRestApi.get("workspaces/#{Workspace.current.id}/obj_classes/#{name}") rescue Scrivito::ClientError raise ResourceNotFound, "Could not find '#{self}' with name '#{name}'." end new(response) end # Creates a new obj class and persists it in the CMS. # # @api public # # This allows you to set the different properties of an obj class by # providing a hash with the property names as keys and the values you want # to set as values. Attributes can be either given as {Scrivito::Attribute} instances or as # an attribute property hash. # # @example Create a non-binary obj class. # ObjClass.create(name: 'Homepage', is_binary: false) # # @example Create a binary obj class. # ObjClass.create(name: 'Image', is_binary: true) # # @example Create an obj class with attributes passed in as an Array of attribute property hashes. # ObjClass.create(name: 'Blog', attributes: [ # { name: 'headline', type: :string }, # { name: 'category', type: :enum, values: %w(tech social) }, # ]) # # @example Create an obj class with attributes passed in as an Array of {Scrivito::Attribute} instances. # ObjClass.create(name: 'Blog', attributes: [ # Attribute.new(name: 'headline', type: :string), # Attribute.new(name: 'category', type: :enum, values: %w(tech social)), # ]) # # @param [Hash] properties # @option properties [String] :name The name of the obj class. # @option properties [Boolean] :is_binary Is this a binary or non-binary obj class? # @option properties [Boolean] :is_active Is it possible to create instances of this obj class? # @option properties [Array, Array] :attributes A list of # attributes for this obj class. Can be either a list of attribute instances or attribute # property hashes. # # @return [Scrivito::ObjClass] def create(properties) properties = properties.with_indifferent_access unless properties.has_key?(:is_binary) raise ScrivitoError, 'The "is_binary" property is mandatory. Please provide' \ ' a hash containing an "is_binary" key with true or false value.' end if properties[:attributes] properties[:attributes].map! do |attribute| attribute.respond_to?(:to_cms_rest_api) ? attribute : Attribute.new(attribute) end end params = format_properties_for_cms(properties) obj_class = new(params) if properties[:attributes] properties[:attributes].each do |attribute| attribute.obj_class = obj_class end end payload = { 'obj_class' => params } response = CmsRestApi.post("workspaces/#{Workspace.current.id}/obj_classes", payload) obj_class.update_instance_properties(response) obj_class end private # Formats obj class properties into a CMS REST API format. # @param [Hash] properties # @return [Hash] Properties formated for the CMS. def format_properties_for_cms(properties) params = properties.dup if params.has_key?(:is_binary) params[:type] = params.delete(:is_binary) ? :generic : :publication end if params.has_key?(:attributes) params[:attributes] = params[:attributes].map do |attribute| attribute.to_cms_rest_api end end params end end # Initializes a new obj class. It expects the CMS backend representation of an obj class. # # See {ObjClass.create} for a detailed overview of how to set properties. # # @param [Hash] properties # @return [Scrivito::ObjClass] # @raise [Scrivito::ScrivitoError] def initialize(properties) update_instance_properties(properties) end # Returns a unique identifier of this obj class. Implements # the {Scrivito::ModelIdentity} interface. # @return [String] def id @name end # Returns the name of this obj class. # @api public # @return [String] def name @name end # Returns if new {Scrivito::BasicObj} instances can be created with this obj class. # @api public # @return [Boolean] def is_active @is_active end alias_method :active?, :is_active # Returns if new {Scrivito::BasicObj} instances created with this obj class are # binary objects like images or PDF documents. # @api public # @return [Boolean] def is_binary @is_binary end alias_method :binary?, :is_binary # Returns the attributes for this obj class. # # @api public # # @example Find an attribute named "locale" for the obj class "Homepage". # ObjClass.find('Homepage').attributes['locale'] # # @example Add a new +string+ attribute named "headline" to the "Homepage" obj class by providing an attribute property hash. # ObjClass.find('Homepage').attributes.add(name: 'headline', type: :string) # # @example Add a new +enum+ attribute named "category" to the "Homepage" obj class by providing an attribute instance. # attribute = Attribute.new(name: 'category', type: :enum, values: %w(tech social)) # ObjClass.find('Homepage').attributes.add(attribute) # # @example Iterate over the list of attributes from the obj class "Homepage" and print their name and type. # ObjClass.find('Homepage').attributes.each do |attribute| # puts "#{attribute.name}:#{attribute.type}" # end # # @return [Scrivito::AttributeCollection] def attributes @attributes end # Updates this obj class and persists the changes in the CMS. It is not possible to # update the +name+ or +is_binary+ property. # # @api public # # See {Scrivito::ObjClass.create} for a detailed overview of # what properties are allowed and how to set them. # # @param [Hash] properties # # @raise [ScrivitoError] Raised when trying to change +name+ or +is_binary+. # # @return [nil] def update(properties) params = properties.with_indifferent_access if params.has_key?(:is_binary) raise ScrivitoError, "#{self.class} does not support changing 'is_binary'. Please remove" \ " the key from the properties." end if params.has_key?(:name) raise ScrivitoError, "#{self.class} does not support changing 'name'. Please remove" \ " the key from the properties." end if params.has_key?(:attributes) params[:attributes].map! do |attribute| unless attribute.respond_to?(:to_cms_rest_api) attribute = Attribute.new(attribute) end attribute.obj_class = self attribute.to_cms_rest_api end end payload = { obj_class: params } response = CmsRestApi.put("workspaces/#{Workspace.current.id}/obj_classes/#{name}", payload) update_instance_properties(response) nil end # Updates the instance properties of this obj class with +properties+ # given in the CMS REST API format. # # @param [Hash] properties # @return [void] def update_instance_properties(properties) properties = properties.with_indifferent_access if properties.has_key?(:type) properties[:is_binary] = %w(image generic).include?(properties[:type]) end @name = properties[:name].to_s @is_active = properties[:is_active] @is_binary = properties[:is_binary] @attributes = create_attribute_collection(properties[:attributes] || []) end private # Creates an attribute collection from an Array of attributes given in the CMS REST API format # and binds all attributes to this obj class. # # @param [Array] attributes # @return [Scrivito::AttributeCollection] def create_attribute_collection(attributes) attributes = attributes.map do |properties| attribute = Attribute.new(properties) attribute.obj_class = self attribute end AttributeCollection.new(self, attributes) end end end