123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- class PerformChanges::Action::AttributeUpdates < PerformChanges::Action
- def execute(...)
- valid_attributes!
- execution_data.each do |key, value|
- next if key.eql?('subscribe') && subscribe(value)
- next if key.eql?('unsubscribe') && unsubscribe(value)
- next if key.eql?('tags') && tags(value)
- next if change_date(key, value, performable)
- exchange_user_id(value)
- template_value(value)
- update_key(key, value['value'])
- end
- end
- private
- def valid_attributes!
- raise "The given #{origin} contains invalid attributes, stopping!" if execution_data.keys.any? { |key| !attribute_valid?(key) }
- true
- end
- def attribute_valid?(attribute)
- return true if %w[tags subscribe unsubscribe].include?(attribute)
- record.class.column_names.include?(attribute)
- end
- def update_key(attribute, value)
- return if record[attribute].to_s.eql?(value.to_s)
- record[attribute] = value
- history(attribute, value)
- end
- def tags(value)
- return if record.class.included_modules.exclude?(HasTags)
- tags = value['value'].split(',')
- return if tags.blank?
- operator = tags_operator(value)
- return if operator.blank?
- tags.each do |tag|
- record.send(:"tag_#{operator}", tag, user_id || 1, sourceable: performable)
- end
- true
- end
- def tags_operator(value)
- operator = value['operator']
- if %w[add remove].exclude?(operator)
- Rails.logger.error "Unknown tags operator #{value['operator']}"
- return
- end
- operator
- end
- def subscribe(value)
- if value['pre_condition'] == 'specific'
- Mention.subscribe! record, User.find_by(id: value['value'])
- else
- Mention.subscribe! record, User.find_by(id: user_id)
- end
- end
- def unsubscribe(value)
- if value['pre_condition'] == 'specific'
- Mention.unsubscribe! record, User.find_by(id: value['value'])
- elsif value['pre_condition'] == 'not_set'
- Mention.unsubscribe_all! record
- else
- Mention.unsubscribe! record, User.find_by(id: user_id)
- end
- end
- def exchange_user_id(value)
- return if !value.key?('pre_condition')
- if value['pre_condition'].start_with?('not_set')
- value['value'] = 1
- elsif value['pre_condition'].start_with?('current_user.')
- # TODO: Check if we have all needed stuff in place (e.g. current_user.organization_id, but it was then also broken before)
- raise __("The required parameter 'user_id' is missing.") if !user_id
- value['value'] = user_id
- end
- true
- end
- def history(attribute, value)
- record.history_change_source_attribute(performable, attribute)
- Rails.logger.debug { "set #{record.class.name.downcase}.#{attribute} = #{value.inspect} for #{record.class.name} with id #{record.id}" }
- end
- def change_date(attribute, value, performable)
- oa = object_manager_attribute(attribute)
- return if oa.blank?
- new_value = fetch_new_date_value(value)
- return if !new_value
- record[attribute] = format_new_date_value(new_value, oa)
- record.history_change_source_attribute(performable, attribute)
- true
- end
- def object_manager_attribute(attribute)
- ObjectManager::Attribute.for_object(record.class.name).find_by(name: attribute, data_type: %w[datetime date])
- end
- def fetch_new_date_value(value)
- case value['operator']
- when 'relative'
- # Clear seconds & miliseconds
- # Because time picker allows to put in hours and minutes only
- # If time contains seconds, detection of changed input malfunctions
- TimeRangeHelper
- .relative(range: value['range'], value: value['value'])
- .change(usec: 0, sec: 0)
- else
- value['value']
- end
- end
- def format_new_date_value(new_value, object_attribute)
- case object_attribute[:data_type]
- when 'datetime'
- new_value.to_datetime
- else
- new_value.to_date
- end
- end
- def template_value(value)
- return value if !value['value'].is_a?(String)
- value['value'] = NotificationFactory::Mailer.template(
- templateInline: value['value'],
- objects: notification_factory_template_objects,
- quote: false,
- locale: locale,
- timezone: timezone,
- )
- true
- end
- end
|