attribute_updates.rb 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. # Copyright (C) 2012-2025 Zammad Foundation, https://zammad-foundation.org/
  2. class PerformChanges::Action::AttributeUpdates < PerformChanges::Action
  3. def execute(...)
  4. valid_attributes!
  5. execution_data.each do |key, value|
  6. next if key.eql?('subscribe') && subscribe(value)
  7. next if key.eql?('unsubscribe') && unsubscribe(value)
  8. next if key.eql?('tags') && tags(value)
  9. next if change_date(key, value, performable)
  10. exchange_user_id(value)
  11. template_value(value)
  12. update_key(key, value['value'])
  13. end
  14. end
  15. private
  16. def valid_attributes!
  17. raise "The given #{origin} contains invalid attributes, stopping!" if execution_data.keys.any? { |key| !attribute_valid?(key) }
  18. true
  19. end
  20. def attribute_valid?(attribute)
  21. return true if %w[tags subscribe unsubscribe].include?(attribute)
  22. record.class.column_names.include?(attribute)
  23. end
  24. def update_key(attribute, value)
  25. return if record[attribute].to_s.eql?(value.to_s)
  26. record[attribute] = value
  27. history(attribute, value)
  28. end
  29. def tags(value)
  30. return if record.class.included_modules.exclude?(HasTags)
  31. tags = value['value'].split(',')
  32. return if tags.blank?
  33. operator = tags_operator(value)
  34. return if operator.blank?
  35. tags.each do |tag|
  36. record.send(:"tag_#{operator}", tag, user_id || 1, sourceable: performable)
  37. end
  38. true
  39. end
  40. def tags_operator(value)
  41. operator = value['operator']
  42. if %w[add remove].exclude?(operator)
  43. Rails.logger.error "Unknown tags operator #{value['operator']}"
  44. return
  45. end
  46. operator
  47. end
  48. def subscribe(value)
  49. user = value['pre_condition'] == 'specific' ? User.find_by(id: value['value']) : User.find_by(id: user_id)
  50. # Ignore it for non-agent users.
  51. return true if !Mention.mentionable?(record, user)
  52. Mention.subscribe! record, user, sourceable: performable
  53. end
  54. def unsubscribe(value)
  55. if value['pre_condition'] == 'specific'
  56. Mention.unsubscribe! record, User.find_by(id: value['value']), sourceable: performable
  57. elsif value['pre_condition'] == 'not_set'
  58. Mention.unsubscribe_all! record, sourceable: performable
  59. else
  60. Mention.unsubscribe! record, User.find_by(id: user_id), sourceable: performable
  61. end
  62. end
  63. def exchange_user_id(value)
  64. return if !value.key?('pre_condition')
  65. if value['pre_condition'].start_with?('not_set')
  66. value['value'] = 1
  67. elsif value['pre_condition'].start_with?('current_user.')
  68. # TODO: Check if we have all needed stuff in place (e.g. current_user.organization_id, but it was then also broken before)
  69. raise __("The required parameter 'user_id' is missing.") if !user_id
  70. value['value'] = user_id
  71. end
  72. true
  73. end
  74. def history(attribute, value)
  75. record.history_change_source_attribute(performable, attribute)
  76. Rails.logger.debug { "set #{record.class.name.downcase}.#{attribute} = #{value.inspect} for #{record.class.name} with id #{record.id}" }
  77. end
  78. def change_date(attribute, value, performable)
  79. oa = object_manager_attribute(attribute)
  80. return if oa.blank?
  81. new_value = fetch_new_date_value(value)
  82. return if !new_value
  83. record[attribute] = format_new_date_value(new_value, oa)
  84. record.history_change_source_attribute(performable, attribute)
  85. true
  86. end
  87. def object_manager_attribute(attribute)
  88. ObjectManager::Attribute.for_object(record.class.name).find_by(name: attribute, data_type: %w[datetime date])
  89. end
  90. def fetch_new_date_value(value)
  91. case value['operator']
  92. when 'relative'
  93. # Clear seconds & miliseconds
  94. # Because time picker allows to put in hours and minutes only
  95. # If time contains seconds, detection of changed input malfunctions
  96. TimeRangeHelper
  97. .relative(range: value['range'], value: value['value'])
  98. .change(usec: 0, sec: 0)
  99. else
  100. value['value']
  101. end
  102. end
  103. def format_new_date_value(new_value, object_attribute)
  104. case object_attribute[:data_type]
  105. when 'datetime'
  106. new_value.to_datetime
  107. else
  108. new_value.to_date
  109. end
  110. end
  111. def template_value(value)
  112. return value if !value['value'].is_a?(String)
  113. value['value'] = NotificationFactory::Mailer.template(
  114. templateInline: value['value'],
  115. objects: notification_factory_template_objects,
  116. quote: false,
  117. locale: locale,
  118. timezone: timezone,
  119. )
  120. true
  121. end
  122. end