module PIM

Constants

DefaultExportFormats

Create Enum type containing all known export formats

EmptyToNilHashAttribute

Special Hash type attribute which will always return ‘nil’ if empty in json

EmptyToNilSetAttribute

Special Set type attribute which will always return ‘nil’ if empty in json

InternalSystemHashAttribute

Internal system attribute of base class ‘Hash’ which does not return it’s value as json

PublicationStatus

Create some system types

Public Class Methods

__after_request() click to toggle source
# File pim.rb, line 645
def self.__after_request

  # Call exit blocks
  request_exit_blocks = Thread.current[:__request_exit_blocks]
  unless request_exit_blocks.nil?

    request_exit_blocks.each do |block_name, block|
      begin
        block.call
      rescue => e
        PIM.log_error "Error executing request exit block '#{block_name}'", e
      end
    end
    Thread.current[:__request_exit_blocks] = nil

  end

  # Reset fiber local caches
  Thread.current[:__caches] = nil

end
__before_request() click to toggle source
# File pim.rb, line 635
def self.__before_request

  # Reset fiber local caches
  Thread.current[:__caches] = nil

  # Reset request exit blocks
  Thread.current[:__request_exit_blocks] = {}

end
__fiber_local_cache(name) click to toggle source
# File pim.rb, line 631
def self.__fiber_local_cache name
  (Thread.current[:__caches] ||= {})[name.to_sym] ||= {}
end
active_module() click to toggle source
# File pim.rb, line 41
def self.active_module
  return @current_active_module if @current_active_module
  return PIM if all_modules.empty?
  @all_modules.values.last
end
additional_attributes_as_json(attribute_names_per_module) click to toggle source
# File pim.rb, line 206
def self.additional_attributes_as_json attribute_names_per_module
  return active_module.additional_attributes_as_json(attribute_names_per_module) if not all_modules.empty?
end
additional_categories_as_json(category_names_per_module) click to toggle source
# File pim.rb, line 202
def self.additional_categories_as_json category_names_per_module
  return active_module.additional_categories_as_json(category_names_per_module) if not all_modules.empty?
end
additional_section_attributes_as_json(layout_name, item) click to toggle source
# File pim.rb, line 210
def self.additional_section_attributes_as_json layout_name, item
  return active_module.additional_section_attributes_as_json(layout_name, item) if not all_modules.empty?
end
after_store(new_item, old_item = nil, opts = {}) click to toggle source
# File pim.rb, line 432
def self.after_store new_item, old_item = nil, opts = {}
  execute_item_method 'after_store', new_item, old_item, opts
end
all_modules() click to toggle source
# File pim.rb, line 33
def self.all_modules
  @all_modules ||= {}
end
at_request_exit(block_name = nil, &block) click to toggle source
# File pim.rb, line 667
def self.at_request_exit block_name = nil, &block

  unless block.nil?

    block_name ||= block.to_s
    request_exit_blocks = (Thread.current[:__request_exit_blocks] ||= {})
    request_exit_blocks[block_name] = block
    return block_name

  end

  unless block_name.nil?
    request_exit_blocks = Thread.current[:__request_exit_blocks]
    return request_exit_blocks.nil? ? nil : request_exit_blocks[block_name]
  end

  return nil

end
attribute_rules_as_json() click to toggle source
# File pim.rb, line 155
def self.attribute_rules_as_json
  return active_module.attribute_rules_as_json if not all_modules.empty?
  return []
end
attributes_as_json() click to toggle source
# File pim.rb, line 122
def self.attributes_as_json
  return active_module.attributes_as_json if not all_modules.empty?
end
before_delete(new_item, opts = {}) click to toggle source
# File pim.rb, line 436
def self.before_delete new_item, opts = {}
  execute_item_method 'before_delete', new_item, nil, opts
end
before_store(old_item, new_item, called_from_import) click to toggle source

Old version: Just for compatibility with projects which directly called this method

# File pim.rb, line 392
def self.before_store old_item, new_item, called_from_import
  return [] if all_modules.empty?

  begin
    old_item = Item.from_json old_item, { :init_multivalue => false } if old_item
  rescue Exception => e
    PIM.log_warn("Could not resolve class of old item in 'before_store' (#{old_item})", e)
  end

  begin
    new_item = Item.from_json new_item, { :init_multivalue => false }
  rescue Exception => e
    PIM.log_warn("Could not resolve class of new item in 'before_store' (#{new_item})", e)
  end

  begin
    if new_item && new_item.kind_of?(Item)
      items_changed = [{ "ORIG" => new_item }]
      before_store = new_item.method(:before_store)
      if before_store.arity == 1 and not called_from_import
        items_changed_in_class = new_item.before_store(old_item)
      elsif before_store.arity == 2
        items_changed_in_class = new_item.before_store(old_item, called_from_import)
      end
      items_changed_in_class.each do |item|
        items_changed << { "SAVE" => item }
      end if items_changed_in_class and items_changed_in_class.respond_to? :each
      return items_changed
    end
  rescue Exception => e
    PIM.log_error("Error in 'before_store'", e)
  end

  return []
end
before_store_v2(new_item, old_item = nil, opts = {}) click to toggle source
# File pim.rb, line 428
def self.before_store_v2 new_item, old_item = nil, opts = {}
  execute_item_method 'before_store', new_item, old_item, opts
end
cache() click to toggle source
# File pim.rb, line 627
def self.cache
  PIM.__fiber_local_cache(:__pim_cache)
end
calculate_category(values) click to toggle source
# File pim.rb, line 615
def self.calculate_category values
  return nil if all_modules.empty?
  values = PIM::Utils.symbolized_hash(values)
  active_module.calculate_category values
end
calculate_primary_key(values) click to toggle source
# File pim.rb, line 621
def self.calculate_primary_key values
  return nil if all_modules.empty?
  values = PIM::Utils.symbolized_hash(values)
  active_module.calculate_primary_key values
end
call_item_method(method_name, new_item, old_item = nil, opts = {}) click to toggle source
# File pim.rb, line 544
def self.call_item_method method_name, new_item, old_item = nil, opts = {}

  method_sym = method_name.to_sym
  return nil if not new_item.respond_to?(method_sym)

  item_method = new_item.method(method_sym)
  arity = item_method.arity.abs
  result = nil

  #
  # Omit calling before_store if we are called in the context
  # of a depublication, and the current datamodel is not aware
  # that this can happen.
  #
  if method_name == 'before_store'
    called_from_depublication = opts[:called_from_depublication] || opts['called_from_depublication']
    if called_from_depublication and not active_module.has_option?(:consider_called_from_depublication)
      PIM.log_debug("Store method '#{method_name}' called from depublication, but current datamodel is not aware of this feature. Invocation will be omitted.")
      return nil
    end
  end

  if method_name == 'before_store' and not active_module.has_option?(:use_before_store_opts)
    # For compatibility: 'before_store' only has the 'called_from_import' parameter
    called_from_import = opts[:called_from_import] || opts['called_from_import']
    if arity == 2
      result = item_method.call(old_item, called_from_import)
    elsif arity == 1
      # For compatibility: Without 'called_from_import' parameter, 'before_store' is not called at all
      if not called_from_import
        result = item_method.call(old_item)
      end
    elsif arity == 0
      result = item_method.call()
    else
      PIM.log_warn("Store method '#{method_name}' does not have the correct number of arguments (#{arity} not in 0, 1 or 2)")
    end
  else
    if arity == 2
      result = item_method.call(old_item, opts)
    elsif arity == 1
      opts[:old_item] = opts['old_item'] = old_item
      result = item_method.call(opts)
    elsif arity == 0
      result = item_method.call()
    else
      PIM.log_warn("Item method '#{method_name}' does not have the correct number of arguments (#{arity} not in 0, 1 or 2)")
    end
  end

  return result

end
categories_as_json() click to toggle source
# File pim.rb, line 126
def self.categories_as_json
  return active_module.categories_as_json if not all_modules.empty?
end
category_as_json(category_name) click to toggle source
# File pim.rb, line 169
def self.category_as_json category_name
  return nil if all_modules.empty?
  category = active_module.category category_name
  return category.as_json if category
end
cleanup_items(items, include_empty) click to toggle source
# File pim.rb, line 532
def self.cleanup_items items, include_empty
  items.map do |item|
    if item.is_a?(PIM::Item)
      json_hash = item.as_json(include_empty: include_empty)
      json_string = json_hash.to_json # Creates a JSON string
      JSON.parse(json_string) # Creates a "cleaned up" JSON Hash
    else
      item
    end
  end
end
communication_channels_as_json() click to toggle source
# File pim.rb, line 142
def self.communication_channels_as_json
  return active_module.communication_channels_as_json if not all_modules.empty?
end
communication_plans_as_json() click to toggle source
# File pim.rb, line 138
def self.communication_plans_as_json
  return active_module.communication_plans_as_json if not all_modules.empty?
end
compute_item_hierarchies_to_publish(primary_keys, publication = nil) click to toggle source

Should not be overridden in data model!

# File pim.rb, line 327
def self.compute_item_hierarchies_to_publish primary_keys, publication = nil

  return {} if active_module.nil?

  if active_module.respond_to?(:compute_item_hierarchies_to_publish)

    # Data model overrides 'compute_item_hierarchies_to_publish'
    PIM.log_info("Data model overrides 'compute_item_hierarchies_to_publish' method")
    return active_module.compute_item_hierarchies_to_publish(primary_keys)

  elsif active_module.respond_to?(:compute_items_to_publish)

    # Data model implements old 'compute_items_to_publish' method
    PIM.log_warn("Data model still implements old 'compute_items_to_publish' method")
    return active_module.compute_items_to_publish(primary_keys)

  else

    # Simple LRU item cache
    item_cache = PIM::LRUCache.new(20)

    # Options to retrieve publication hierarchies
    publication_type = PIM.get_value(publication, 'publication_type')

    publication_values = PIM.get_value(publication, 'publication_values')
    publish_only_valid = PIM.get_value(publication_values, 'only_valid')
    if publish_only_valid.nil?
      publish_only_valid = publication_type.nil? || publication_type == 'ADD'
    else
      publish_only_valid = publish_only_valid.to_s.downcase == 'true'
    end

    opts = {
      :item_cache => item_cache,
      :only_valid => publish_only_valid,
      :publication => (publication || {})
    }

    # Step one: Determine the top level items for the hierarchies to publish
    top_level_items = active_module.get_top_level_items(primary_keys, opts)

    # Step two: Determine the hierarchies for each top level item
    item_hierarchies = {}

    top_level_items.each do |top_level_item, status|

      # Set status from top_level_item result
      opts[:status] = status

      item_hierarchy = active_module.get_item_hierarchy(top_level_item, opts)
      item_hierarchy = active_module.update_hierarchy(item_hierarchy, opts)
      item_hierarchies[top_level_item] = item_hierarchy unless item_hierarchy.nil?

    end

    return item_hierarchies

  end
end
contact_attributes_as_json() click to toggle source
# File pim.rb, line 99
def self.contact_attributes_as_json
  return active_module.contact_attributes if not all_modules.empty?
  return []
end
copy_item_as_json(item, organization) click to toggle source
# File pim.rb, line 179
def self.copy_item_as_json item, organization
  return nil if all_modules.empty?
  copy = active_module.copy_item item, organization
  return copy.as_json if copy
end
dashboard_attributes_as_json() click to toggle source
# File pim.rb, line 109
def self.dashboard_attributes_as_json
  return active_module.dashboard_attributes if not all_modules.empty?
  return []
end
data_model_as_json() click to toggle source
# File pim.rb, line 114
def self.data_model_as_json
  return active_module.data_model_as_json if not all_modules.empty?
end
data_model_services(service_data_model_hash_map = nil) click to toggle source
# File pim.rb, line 79
def self.data_model_services service_data_model_hash_map = nil
  @service_data_model_hash_map = service_data_model_hash_map unless service_data_model_hash_map.nil?
  @service_data_model_hash_map
end
default_item_as_json(category_name, organization, user) click to toggle source
# File pim.rb, line 185
def self.default_item_as_json category_name, organization, user
  return nil if all_modules.empty?
  category = active_module.category category_name
  if category and category.respond_to?(:default_item)
    organization = PIM::Services.__convert(organization, to: PIM::Services::OrganizationService::Organization)
    user = PIM::Services.__convert(user, to: PIM::Services::AccountService::LoginAccount)

    arity = category.method(:default_item).arity
    item = case arity
      when 2 then category.default_item(organization, user)
      when 1 then category.default_item(organization)
      else category.default_item
    end
    return item.as_json if !item.nil?
  end
end
execute_item_method(method_name, new_item, old_item = nil, opts = {}) click to toggle source
# File pim.rb, line 440
def self.execute_item_method method_name, new_item, old_item = nil, opts = {}

  return {} if all_modules.empty?

  begin
    new_item = PIM::Item.from_json(new_item, :init_multivalue => false)
  rescue Exception => e
    PIM.log_warn("Could not create new item in '#{method_name}' for:\n#{new_item}", e)
  end
  return {} if not new_item.is_a?(PIM::Item)

  old_item ||= opts[:old_item]
  if old_item
    begin
      old_item = PIM::Item.from_json(old_item, :init_multivalue => false)
    rescue Exception => e
      PIM.log_warn("Could not create old item in '#{method_name}' for:\n#{old_item}", e)
    end
    old_item = nil if not old_item.is_a?(PIM::Item)
  end

  begin
    method_call_result = self.call_item_method(method_name, new_item, old_item, opts)
  rescue Exception => e
    PIM.log_error("Error calling '#{method_name}' method", e)
    return { "exception" => e.message }
  end

  result = {}

  include_empty = active_module.has_option?(:return_empty_values)

  if method_name == 'before_store'

    # Check if 'store_item' was set to false
    if PIM.get_value(method_call_result, :store_item) == false

      # NOTE: We could allow to set 'store_item' to a Hash in order to store the item as specified!
      # This way we would not merge the item with the old values at all!
      result['this'] = false
      result['call_after_store'] = false

    else

      result['this'] = new_item.as_json(:include_empty => include_empty)
      result['call_after_store'] = (self.call_item_method('call_after_store?', new_item, old_item, opts) == true)

    end

  end

  if not is_empty?(method_call_result)
    if is_array?(method_call_result)
      result['others'] = self.cleanup_items(method_call_result, include_empty)
    elsif is_hash?(method_call_result)

      # Set 'status_values' from call result, if any
      self.set_javaify_method_call_result(result, method_call_result, :status_values)

      # Set 'item_hierarchies' from call result, if any
      self.set_javaify_method_call_result(result, method_call_result, :item_hierarchies)

      # Convert and add store_options and store_items to actual result
      result_others = {}

      # Use 'javaify' to convert the options to ensure no Ruby Symbol objects are used in Java
      self.set_javaify_method_call_result(result_others, method_call_result, :store_options)
      self.set_javaify_method_call_result(result_others, method_call_result, :delete_items)
      self.set_javaify_method_call_result(result_others, method_call_result, :validate_items)

      # Set items to store as "cleaned up" JSON
      self.set_method_call_result(result_others, method_call_result, :store_items) { |items| PIM.cleanup_items(items, include_empty: include_empty) }

      result['others'] = result_others unless PIM.is_empty?(result_others)

    end
  end

  return result

end
execute_plan_action(action_type, action_creator, action_tags, action_date, channel, organization, data) click to toggle source
# File pim.rb, line 387
def self.execute_plan_action action_type, action_creator, action_tags, action_date, channel, organization, data
  return active_module.execute_plan_action(action_type, action_creator, action_tags, action_date, channel, organization, data) if not all_modules.empty?
end
filters_as_json() click to toggle source
# File pim.rb, line 134
def self.filters_as_json
  return active_module.filters_as_json if not all_modules.empty?
end
has_module?(module_name) click to toggle source
# File pim.rb, line 37
def self.has_module? module_name
  @all_modules && @all_modules.include?(module_name.to_s)
end
in_platform_publication_as_json() click to toggle source
# File pim.rb, line 146
def self.in_platform_publication_as_json
  return as_json(active_module.in_platform_publication) if not all_modules.empty?
end
item_hierarchy_graph(item, hierarchy_name = nil) click to toggle source

Return an item hierarchy graph for the specified item and hierarchy name. If hiearchy_name is nil, returns the “default” hierarchy.

The resulted hierarchy should have the following JSON structure:
 {
   "items": [
       {
           "primaryKey": "22222",    <- Primary key of the item in the hierarchy
           "level": 1                <- Level of hierarchy, starts with 0
       },
       ...
   ], // Alternatively, it is also possible to use primary keys only,
        e.g. items: [ "1234", "4567", ... ] however no mixture of both!
   "relations": [
       {
           "parentItem": "",         <- Primary key of the parent item
           "childItem": "",          <- Primary key of the child item
           "relationValue": "20x",   <- Value of the relationship (optional)
           "relationAttribute": "amount" <- The unit of the relationship (optional)
       },
       ...
   ]

}

# File pim.rb, line 262
def self.item_hierarchy_graph item, hierarchy_name = nil

  return nil if all_modules.empty?

  if is_hash?(item)
    begin
      item = Item.from_json(item, { :init_multivalue => false })
    rescue Exception => e
      PIM.log_warn("Could not create item in 'item_hierarchy_graph' for:\n#{item}", e)
    end
  elsif is_string?(item)
    primary_key = item
    item = PIM::Services::ItemService.get_item_as_ruby(primary_key, :init_multivalue => false)
    PIM.log_warn("Item for primary key '#{primary_key}' in item_hierarchy_graph not found") if item.nil?
  end
  return nil if not item.is_a?(Item)

  # Get hierarchy graph for item
  hierarchy_graph = item.method(:hierarchy_graph)
  if hierarchy_graph
    arity = hierarchy_graph.arity
    hierarchy = case arity
      when 0 then item.hierarchy_graph()
      when 1, -1 then item.hierarchy_graph(hierarchy_name)
      when 2, -2 then item.hierarchy_graph(hierarchy_name, {})
      else
        PIM.log_warn("'hierarchy_graph' method for category #{item.class} does not have the correct number of arguments (#{arity.abs} not in 0, 1 or 2)")
        nil
    end
  else
    PIM.log_info("No 'hierarchy_graph' method in category #{item.class}")
    hierarchy = nil
  end

  if is_hash?(hierarchy)
    hierarchy[:items].map! { |item| camelize(item) } if hierarchy[:items]
    hierarchy[:relations].map! { |relation| camelize(relation) } if hierarchy[:relations]
  end

  return hierarchy

end
layout_as_json(layout_name, opts = {}) click to toggle source
# File pim.rb, line 225
def self.layout_as_json layout_name, opts = {}
  return nil if all_modules.empty?
  layout = active_module.layout layout_name
  return layout.as_json(opts) if layout
end
layouts_as_json() click to toggle source
# File pim.rb, line 130
def self.layouts_as_json
  return active_module.layouts_as_json if not all_modules.empty?
end
managing_user_roles_as_json(user, contact) click to toggle source
# File pim.rb, line 218
  def self.managing_user_roles_as_json user, contact
    # FIXME: Add 'Contact' class in 'ContactService' to support execution on external Ruby!
#    user = PIM::Services.__convert(user, to: PIM::Services::AccountService::LoginAccount)
#    contact = PIM::Services.__convert(contact, to: PIM::Services::ContactService::Contact)
    return active_module.managing_user_roles_as_json(user, contact) if not all_modules.empty?
  end
mapping_functions_as_json() click to toggle source
# File pim.rb, line 175
def self.mapping_functions_as_json
  return active_module.mapping_functions_as_json if not all_modules.empty?
end
media_asset_naming_patterns_as_json() click to toggle source
# File pim.rb, line 160
def self.media_asset_naming_patterns_as_json
  return as_json(active_module.media_asset_naming_patterns)
end
merge_item_reviews(new_item_review, old_item_review) click to toggle source

We expect the passed itemReviews formatted as JSON strings

# File pim.rb, line 308
def self.merge_item_reviews new_item_review, old_item_review
  new_item_review_hash = JSON.parse(new_item_review)

  new_item_review = ItemReview.new(new_item_review_hash)
  old_item_review = ItemReview.new(JSON.parse(old_item_review))

  result = active_module.merge_item_reviews(new_item_review, old_item_review)

  return nil if result.nil?

  result.as_json
        .select {|k,v| ItemReview::WRITABLE_MEMBERS.include?(k)}
        .each_pair {|k,v| new_item_review_hash[k] = v}

  return new_item_review_hash

end
migrate_as_json(args) click to toggle source
# File pim.rb, line 231
def self.migrate_as_json args
  return nil if all_modules.empty?
  migrated_values = active_module.migrate!(args)
  return as_json(migrated_values)
end
option_lists_as_json() click to toggle source
# File pim.rb, line 118
def self.option_lists_as_json
  return active_module.option_lists_as_json if not all_modules.empty?
end
organization_attributes_as_json() click to toggle source
# File pim.rb, line 89
def self.organization_attributes_as_json
  return active_module.organization_attributes if not all_modules.empty?
  return []
end
print_json(object) click to toggle source
reset() click to toggle source
# File pim.rb, line 47
def self.reset
  all_modules.keys.each do |m|
    PIM::Utils.remove_const_on_parent m
  end
  @all_modules = nil
end
reset_active_module() click to toggle source
# File pim.rb, line 54
def self.reset_active_module
  return if all_modules.empty?
  active_module_key = active_module.to_s
  PIM::Utils.remove_const_on_parent(active_module_key)
  new_all_modules = @all_modules.dup
  new_all_modules.delete(active_module_key)
  @all_modules = new_all_modules
end
return_json(object) click to toggle source
# File pim.rb, line 68
def self.return_json object
  return object.is_a?(String)? object : as_json(object).to_json if object
end
review_attributes_as_json() click to toggle source
# File pim.rb, line 104
def self.review_attributes_as_json
  return active_module.review_attributes if not all_modules.empty?
  return []
end
roles_as_json() click to toggle source
# File pim.rb, line 84
def self.roles_as_json
  return active_module.roles_as_json if not all_modules.empty?
  return PIM.all_roles_as_json
end
set_javaify_method_call_result(result, method_call_result, key) click to toggle source
# File pim.rb, line 528
def self.set_javaify_method_call_result result, method_call_result, key
  self.set_method_call_result(result, method_call_result, key) { |v| PIM.javaify(v) }
end
set_method_call_result(result, method_call_result, key, &convert_block) click to toggle source
# File pim.rb, line 522
def self.set_method_call_result result, method_call_result, key, &convert_block
  value = PIM.get_value(method_call_result, key)
  value = convert_block.call(value) unless value.nil?
  result[key.to_s] = value unless PIM.is_empty?(value)
end
task_tags_as_json() click to toggle source
# File pim.rb, line 150
def self.task_tags_as_json
  return as_json(active_module.task_tags) if not all_modules.empty?
  return []
end
to_json(object) click to toggle source
# File pim.rb, line 72
def self.to_json object
  return nil if object.nil?
  return object if object.is_a?(String)
  return object.to_json if object.respond_to?(:to_json)
  return object.to_s
end
user_attributes_as_json() click to toggle source
# File pim.rb, line 94
def self.user_attributes_as_json
  return active_module.user_attributes if not all_modules.empty?
  return []
end
user_data_model_as_json(user) click to toggle source
# File pim.rb, line 214
def self.user_data_model_as_json user
  return active_module.user_data_model_as_json(user) if not all_modules.empty?
end
validate_as_json(old_item, new_item, attributes = nil) click to toggle source
# File pim.rb, line 598
def self.validate_as_json old_item, new_item, attributes = nil
  return nil if all_modules.empty?

  old_item = PIM::Utils.symbolized_hash(old_item)
  new_item = PIM::Utils.symbolized_hash(new_item)
  attributes = PIM::Utils.symbolized_array(attributes)

  validation_result = active_module.validate old_item, new_item, *attributes
  validation_result.as_json

end
validate_items_as_json(items) click to toggle source
# File pim.rb, line 610
def self.validate_items_as_json items
  return nil if all_modules.empty?
  return as_json(active_module.validate_items(*items))
end

Protected Class Methods

execute_in_module(execute_module, &block) click to toggle source
# File pim.rb, line 689
def self.execute_in_module execute_module, &block
  old_active_module = @current_active_module
  begin
    execute_module = get_module(execute_module)
    return nil if !execute_module
    @current_active_module = execute_module
    return execute_module.module_exec(&block)
  ensure
    @current_active_module = old_active_module
  end
end