app/models/concerns/checks_human_changes.rb
# Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
module ChecksHumanChanges
extend ActiveSupport::Concern
def human_changes(record_changes, record, user = nil)
return {} if record_changes.blank?
locale = user.try(:locale) || Setting.get('locale_default') || 'en-us'
attribute_list = allowed_attributes(record.class.name, user)
user_related_changes = user_changes(record_changes, attribute_list)
readable_changes(record, user_related_changes, attribute_list, locale)
end
private
def allowed_attributes(object, user)
ObjectManager::Object.new(object).attributes(user, skip_permission: user.nil?).index_by { |item| item[:name] }
end
def user_changes(record_changes, attribute_list)
user_related_changes = {}
record_changes.each do |key, value|
# If no config exists, use all attributes or if config exists, just use
# existing attributes for user
if attribute_list.blank? || attribute_list[key.to_s]
user_related_changes[key] = value
end
end
user_related_changes
end
def readable_changes(record, user_related_changes, attribute_list, locale)
changes = {}
user_related_changes.each do |key, value|
is_relation_field = key.to_s.end_with?('_id')
attribute_name = attribute_name(is_relation_field, key)
if is_relation_field
value = id_to_relation_value(record, attribute_name, value)
end
attribute = attribute_list&.dig(key.to_s)
display = display_name(attribute) || attribute_name
changes[display] = display_value(locale, value, attribute)
end
changes
end
def attribute_name(is_relation_field, key)
attribute_name = key.to_s
return attribute_name[0..-4] if is_relation_field
attribute_name
end
def id_to_relation_value(record, attribute_name, value)
relation_class = record.public_send(attribute_name)&.class
value.map do |id|
next id if !relation_class
relation_model_visible_value(relation_class, id)
end
end
def relation_model_visible_value(relation_class, id)
relation_model = relation_class.lookup(id: id)
return id.to_s if !relation_model
return relation_model['name'] if relation_model['name']
return relation_model.fullname if relation_model.respond_to?(:fullname)
id
end
def display_name(attribute)
return attribute[:display].to_s if attribute && attribute[:display]
nil
end
def display_value(locale, value, attribute)
if attribute && attribute[:translate]
return [Translation.translate(locale, value[0]), Translation.translate(locale, value[1])]
end
[value[0].to_s, value[1].to_s]
end
end