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 Workspace.current.obj_classes.to_a 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) obj_class = Workspace.current.obj_classes[name] unless obj_class raise ResourceNotFound, "Could not find '#{ObjClass}' with name '#{name}'." end obj_class 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 workspace = Workspace.current raw_obj_class_data = workspace.api_request(:post, '/obj_classes', obj_class: format_properties_for_cms(properties)) new(ObjClassData.new(raw_obj_class_data), workspace) 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(&:to_cms_rest_api) 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] obj_class_data # @param [Workspace,NilClass] workspace # @raise [Scrivito::ScrivitoError] # @return [Scrivito::ObjClass] def initialize(obj_class_data, workspace) update_obj_class_data(obj_class_data) @workspace = workspace end # @!attribute [r] id # @api public # @return [String] unique identifier of this obj class # @!attribute [r] name # @api public # @return [String] the name of this obj class # @!attribute [r] is_active # @api public # @return [Boolean] whether instances can be created with this obj class # @!attribute [r] is_binary # @api public # @return [Boolean] whether instances of this class are binary, e.g. images or PDFs delegate :id, :name, :is_active, :is_binary, to: :obj_class_data alias_method :active?, :is_active alias_method :binary?, :is_binary # @api public # @return [Scrivito::AttributeCollection] the attributes of this obj class. # # @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 attr_reader :attributes # 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| attribute = Attribute.new(attribute) unless attribute.respond_to?(:to_cms_rest_api) attribute.obj_class = self attribute.to_cms_rest_api end end raw_obj_class_data = workspace.api_request(:put, "/obj_classes/#{name}", obj_class: params) update_obj_class_data(ObjClassData.new(raw_obj_class_data)) workspace.reload nil end def update_obj_class_data(obj_class_data) @obj_class_data = obj_class_data update_attributes end private attr_reader :obj_class_data, :workspace def update_attributes attributes = @obj_class_data.attributes.map do |attribute_data| attribute = Attribute.new(attribute_data) attribute.obj_class = self attribute end @attributes = AttributeCollection.new(self, attributes) end end end