attribute_updates.rb 3.6 KB

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