result.rb 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. class CoreWorkflow::Result
  3. include ::Mixin::HasBackends
  4. attr_accessor :payload, :payload_backup, :user, :assets, :assets_in_result, :result, :rerun, :form_updater, :restricted_fields
  5. def initialize(payload:, user:, assets: {}, assets_in_result: true, result: {}, form_updater: false)
  6. raise ArgumentError, __("The required parameter 'payload->class_name' is missing.") if !payload['class_name']
  7. raise ArgumentError, __("The required parameter 'payload->screen' is missing.") if !payload['screen']
  8. @restricted_fields = {}
  9. @payload = payload
  10. @payload_backup = Marshal.load(Marshal.dump(payload))
  11. @user = user
  12. @assets = assets
  13. @assets_in_result = assets_in_result
  14. @result = result
  15. @form_updater = form_updater
  16. @rerun = false
  17. end
  18. def attributes
  19. @attributes ||= CoreWorkflow::Attributes.new(result_object: self)
  20. end
  21. def workflows
  22. CoreWorkflow.active.object(payload['class_name'])
  23. end
  24. def set_default
  25. @rerun = false
  26. set_payload_body
  27. set_payload_customer_id_default
  28. @result[:restrict_values] = {}
  29. %i[request_id visibility mandatory readonly select fill_in eval matched_workflows rerun_count].each do |group|
  30. @result[group] = attributes.send(:"#{group}_default")
  31. end
  32. set_form_updater_default
  33. # restrict init defaults to make sure param values to removed if not allowed
  34. attributes.restrict_values_default.each do |field, values|
  35. # skip initial rerun to improve performance
  36. # priority e.g. would trigger a rerun because its not set yet
  37. # but we skip rerun here because the initial values have no logic which
  38. # are dependent on form changes
  39. run_backend_value('set_fixed_to', field, values, skip_rerun: true, skip_mark_restricted: true)
  40. end
  41. set_default_only_shown_if_selectable
  42. end
  43. def set_payload_body
  44. @payload['params']['body'] = @payload.dig('params', 'article', 'body')
  45. end
  46. def set_payload_customer_id_default
  47. return if !@payload['params']['customer_id'].nil?
  48. return if !@user
  49. return if !@user.permissions?('ticket.customer')
  50. return if @user.permissions?('ticket.agent')
  51. @payload['params']['customer_id'] = @user.id.to_s
  52. end
  53. def set_form_updater_default
  54. return if !form_updater
  55. @result[:all_options] = attributes.all_options_default
  56. @result[:historical_options] = attributes.historical_options_default
  57. end
  58. def set_default_only_shown_if_selectable
  59. # only_shown_if_selectable should not work on bulk feature
  60. return if @payload['screen'] == 'overview_bulk'
  61. auto_hide = {}
  62. attributes.auto_select_default.each do |field, state|
  63. result = run_backend_value('auto_select', field, state)
  64. next if result.compact.blank?
  65. auto_hide[field] = true
  66. end
  67. auto_hide.each do |field, state|
  68. run_backend_value('hide', field, state)
  69. end
  70. end
  71. def run
  72. set_default
  73. workflows.each do |workflow|
  74. condition = CoreWorkflow::Condition.new(result_object: self, workflow: workflow)
  75. next if !condition.match_all?
  76. run_workflow(workflow)
  77. run_custom(workflow, condition)
  78. match_workflow(workflow)
  79. break if workflow.stop_after_match
  80. end
  81. consider_rerun
  82. end
  83. def matches_selector?(selector:, check:)
  84. condition_object = CoreWorkflow::Condition.new(result_object: self)
  85. condition_object.check = check
  86. condition_object.condition_selector_match?(selector)
  87. end
  88. def run_workflow(workflow)
  89. Array(workflow.perform).each do |field, config|
  90. run_backend(field, config)
  91. end
  92. end
  93. def run_custom(workflow, condition)
  94. Array(workflow.perform.dig('custom.module', 'execute')).each do |module_path|
  95. custom_module = module_path.constantize.new(condition_object: condition, result_object: self)
  96. custom_module.perform
  97. end
  98. end
  99. def run_backend(field, perform_config, skip_rerun: false, skip_mark_restricted: false)
  100. result = []
  101. Array(perform_config['operator']).each do |backend|
  102. result << "CoreWorkflow::Result::#{backend.classify}".constantize.new(result_object: self, field: field, perform_config: perform_config, skip_rerun: skip_rerun, skip_mark_restricted: skip_mark_restricted).run
  103. end
  104. result
  105. end
  106. def run_backend_value(backend, field, value, skip_rerun: false, skip_mark_restricted: false)
  107. perform_config = {
  108. 'operator' => backend,
  109. backend => value,
  110. }
  111. run_backend(field, perform_config, skip_rerun: skip_rerun, skip_mark_restricted: skip_mark_restricted)
  112. end
  113. def change_flags(flags)
  114. @result[:flags] ||= {}
  115. @result[:flags] = @result[:flags].merge(flags)
  116. end
  117. def match_workflow(workflow)
  118. @result[:matched_workflows] |= Array(workflow.id)
  119. end
  120. def assets_in_result?
  121. return false if assets == false
  122. return false if !@assets_in_result
  123. @result[:assets] = assets
  124. true
  125. end
  126. def workflow_restricted_fields
  127. @workflow_restricted_fields ||= begin
  128. result = []
  129. workflows.each do |workflow|
  130. fields = workflow.perform.each_with_object([]) do |(key, value), result_inner|
  131. next if %w[select remove_option set_fixed_to add_option].exclude?(value['operator'])
  132. result_inner << key.split('.')[-1]
  133. end
  134. result |= fields
  135. end
  136. result
  137. end
  138. end
  139. def filter_restrict_values
  140. @result[:restrict_values].select! do |field, _values|
  141. attribute = attributes.object_elements_hash[field]
  142. next if attribute && workflow_restricted_fields.exclude?(field) && !@restricted_fields[field] && !attributes.attribute_options_relation?(attribute) && !attributes.attribute_filter?(attribute)
  143. true
  144. end
  145. end
  146. def consider_rerun
  147. if @rerun && @result[:rerun_count] < 25
  148. @result[:rerun_count] += 1
  149. return run
  150. end
  151. filter_restrict_values if !@form_updater
  152. assets_in_result?
  153. @result
  154. end
  155. end