can_lookup_search_index_attributes.rb 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. module ApplicationModel::CanLookupSearchIndexAttributes
  3. extend ActiveSupport::Concern
  4. class RequestCache < ActiveSupport::CurrentAttributes
  5. attribute :integer_attribute_names
  6. def integer_fields(class_name)
  7. self.integer_attribute_names ||= {}
  8. updated_at = ObjectManager::Attribute.maximum('updated_at')
  9. return self.integer_attribute_names[class_name][:data] if self.integer_attribute_names[class_name].present? && self.integer_attribute_names[class_name][:updated_at] == updated_at
  10. self.integer_attribute_names[class_name] = {
  11. updated_at: updated_at,
  12. data: ObjectManager::Attribute.where(object_lookup: ObjectLookup.find_by(name: class_name), data_type: 'integer', editable: true).pluck(:name),
  13. }
  14. self.integer_attribute_names[class_name][:data]
  15. end
  16. end
  17. =begin
  18. This function return the attributes for the elastic search with relation hash values.
  19. It can be run with parameter include_references: false to skip the relational hashes to prevent endless loops.
  20. ticket = Ticket.find(3)
  21. attributes = ticket.search_index_attribute_lookup
  22. attributes = ticket.search_index_attribute_lookup(include_references: false)
  23. returns
  24. attributes # object with lookup data
  25. =end
  26. def search_index_attribute_lookup(include_references: true)
  27. attributes = self.attributes
  28. self.attributes.each do |key, value|
  29. break if !include_references
  30. attribute_name = key.to_s
  31. # ignore standard attribute if needed
  32. if self.class.search_index_attribute_ignored?(attribute_name)
  33. attributes.delete(attribute_name)
  34. next
  35. end
  36. # need value for reference data
  37. next if !value
  38. # check if we have a referenced object which we could include here
  39. next if !search_index_attribute_method(attribute_name)
  40. # get referenced attribute name
  41. attribute_ref_name = self.class.search_index_attribute_ref_name(attribute_name)
  42. next if !attribute_ref_name
  43. # ignore referenced attributes if needed
  44. next if self.class.search_index_attribute_ignored?(attribute_ref_name)
  45. # get referenced attribute value
  46. value = search_index_value_by_attribute(attribute_name)
  47. next if !value
  48. # save name of ref object
  49. attributes[ attribute_ref_name ] = value
  50. end
  51. if is_a? HasObjectManagerAttributes
  52. RequestCache.integer_fields(self.class.to_s).each do |field|
  53. next if attributes[field].blank?
  54. attributes["#{field}_text"] = attributes[field].to_s
  55. end
  56. end
  57. attributes
  58. end
  59. =begin
  60. This function returns the relational search index value based on the attribute name.
  61. organization = Organization.find(1)
  62. value = organization.search_index_value_by_attribute('organization_id')
  63. returns
  64. value = {"name"=>"Zammad Foundation"}
  65. =end
  66. def search_index_value_by_attribute(attribute_name = '')
  67. # get attribute name
  68. relation_class = search_index_attribute_method(attribute_name)
  69. return if !relation_class
  70. # lookup ref object
  71. relation_model = relation_class.lookup(id: attributes[attribute_name])
  72. return if !relation_model
  73. relation_model.search_index_attribute_lookup(include_references: false)
  74. end
  75. =begin
  76. This function returns the method for the relational search index attribute.
  77. method = Ticket.new.search_index_attribute_method('organization_id')
  78. returns
  79. method = Organization (class)
  80. =end
  81. def search_index_attribute_method(attribute_name = '')
  82. return if attribute_name[-3, 3] != '_id'
  83. attribute_name = attribute_name[ 0, attribute_name.length - 3 ]
  84. return if !respond_to?(attribute_name)
  85. send(attribute_name).class
  86. end
  87. class_methods do
  88. =begin
  89. This function returns the relational search index attribute name for the given class.
  90. attribute_ref_name = Organization.search_index_attribute_ref_name('user_id')
  91. returns
  92. attribute_ref_name = 'user'
  93. =end
  94. def search_index_attribute_ref_name(attribute_name)
  95. attribute_name[ 0, attribute_name.length - 3 ]
  96. end
  97. =begin
  98. This function returns if a search index attribute should be ignored.
  99. ignored = Ticket.search_index_attribute_ignored?('organization_id')
  100. returns
  101. ignored = false
  102. =end
  103. def search_index_attribute_ignored?(attribute_name = '')
  104. ignored_attributes = instance_variable_get(:@search_index_attributes_ignored) || []
  105. return if ignored_attributes.blank?
  106. ignored_attributes.include?(attribute_name.to_sym)
  107. end
  108. =begin
  109. This function returns if a search index attribute is relevant for creating/updating the search index for this object.
  110. relevant = Ticket.search_index_attribute_relevant?('organization_id')
  111. returns
  112. relevant = true
  113. =end
  114. def search_index_attribute_relevant?(attribute_name = '')
  115. relevant_attributes = instance_variable_get(:@search_index_attributes_relevant) || []
  116. return true if relevant_attributes.blank?
  117. relevant_attributes.include?(attribute_name.to_sym)
  118. end
  119. end
  120. end