result.rb 6.0 KB

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