attribute_updates.rb 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. # Copyright (C) 2012-2024 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. if value['pre_condition'] == 'specific'
  50. Mention.subscribe! record, User.find_by(id: value['value'])
  51. else
  52. Mention.subscribe! record, User.find_by(id: user_id)
  53. end
  54. end
  55. def unsubscribe(value)
  56. if value['pre_condition'] == 'specific'
  57. Mention.unsubscribe! record, User.find_by(id: value['value'])
  58. elsif value['pre_condition'] == 'not_set'
  59. Mention.unsubscribe_all! record
  60. else
  61. Mention.unsubscribe! record, User.find_by(id: user_id)
  62. end
  63. end
  64. def exchange_user_id(value)
  65. return if !value.key?('pre_condition')
  66. if value['pre_condition'].start_with?('not_set')
  67. value['value'] = 1
  68. elsif value['pre_condition'].start_with?('current_user.')
  69. # TODO: Check if we have all needed stuff in place (e.g. current_user.organization_id, but it was then also broken before)
  70. raise __("The required parameter 'user_id' is missing.") if !user_id
  71. value['value'] = user_id
  72. end
  73. true
  74. end
  75. def history(attribute, value)
  76. record.history_change_source_attribute(performable, attribute)
  77. Rails.logger.debug { "set #{record.class.name.downcase}.#{attribute} = #{value.inspect} for #{record.class.name} with id #{record.id}" }
  78. end
  79. def change_date(attribute, value, performable)
  80. oa = object_manager_attribute(attribute)
  81. return if oa.blank?
  82. new_value = fetch_new_date_value(value)
  83. return if !new_value
  84. record[attribute] = format_new_date_value(new_value, oa)
  85. record.history_change_source_attribute(performable, attribute)
  86. true
  87. end
  88. def object_manager_attribute(attribute)
  89. ObjectManager::Attribute.for_object(record.class.name).find_by(name: attribute, data_type: %w[datetime date])
  90. end
  91. def fetch_new_date_value(value)
  92. case value['operator']
  93. when 'relative'
  94. # Clear seconds & miliseconds
  95. # Because time picker allows to put in hours and minutes only
  96. # If time contains seconds, detection of changed input malfunctions
  97. TimeRangeHelper
  98. .relative(range: value['range'], value: value['value'])
  99. .change(usec: 0, sec: 0)
  100. else
  101. value['value']
  102. end
  103. end
  104. def format_new_date_value(new_value, object_attribute)
  105. case object_attribute[:data_type]
  106. when 'datetime'
  107. new_value.to_datetime
  108. else
  109. new_value.to_date
  110. end
  111. end
  112. def template_value(value)
  113. return value if !value['value'].is_a?(String)
  114. value['value'] = NotificationFactory::Mailer.template(
  115. templateInline: value['value'],
  116. objects: notification_factory_template_objects,
  117. quote: false,
  118. locale: locale,
  119. timezone: timezone,
  120. )
  121. true
  122. end
  123. end