search.rb 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. module Ticket::Search
  3. extend ActiveSupport::Concern
  4. # methods defined here are going to extend the class, not the instance of it
  5. class_methods do
  6. =begin
  7. search tickets preferences
  8. result = Ticket.search_preferences(user_model)
  9. returns if user has permissions to search
  10. result = {
  11. prio: 3000,
  12. direct_search_index: false
  13. }
  14. returns if user has no permissions to search
  15. result = false
  16. =end
  17. def search_preferences(_current_user)
  18. {
  19. prio: 3000,
  20. direct_search_index: false,
  21. }
  22. end
  23. =begin
  24. search tickets via search index
  25. result = Ticket.search(
  26. current_user: User.find(123),
  27. query: 'search something',
  28. limit: 15,
  29. offset: 100,
  30. )
  31. returns
  32. result = [ticket_model1, ticket_model2]
  33. search tickets via search index
  34. result = Ticket.search(
  35. current_user: User.find(123),
  36. query: 'search something',
  37. limit: 15,
  38. offset: 100,
  39. full: false,
  40. )
  41. returns
  42. result = [1,3,5,6,7]
  43. search tickets via database
  44. result = Ticket.search(
  45. current_user: User.find(123),
  46. query: 'some query', # query or condition is required
  47. condition: {
  48. 'tickets.owner_id' => {
  49. operator: 'is',
  50. value: user.id,
  51. },
  52. 'tickets.state_id' => {
  53. operator: 'is',
  54. value: Ticket::State.where(
  55. state_type_id: Ticket::StateType.where(
  56. name: [
  57. 'pending reminder',
  58. 'pending action',
  59. ],
  60. ).map(&:id),
  61. },
  62. ),
  63. },
  64. limit: 15,
  65. offset: 100,
  66. full: false,
  67. )
  68. returns
  69. result = [1,3,5,6,7]
  70. =end
  71. def search(params)
  72. # get params
  73. query = params[:query]
  74. condition = params[:condition]
  75. limit = params[:limit] || 12
  76. offset = params[:offset] || 0
  77. current_user = params[:current_user]
  78. full = false
  79. if params[:full] == true || params[:full] == 'true' || !params.key?(:full)
  80. full = true
  81. end
  82. # try search index backend
  83. if condition.blank? && SearchIndexBackend.enabled?
  84. query_extention = {}
  85. query_extention['bool'] = {}
  86. query_extention['bool']['must'] = []
  87. if current_user.permissions?('ticket.agent')
  88. group_ids = current_user.group_ids_access('read')
  89. access_condition = {
  90. 'query_string' => { 'default_field' => 'group_id', 'query' => "\"#{group_ids.join('" OR "')}\"" }
  91. }
  92. else
  93. access_condition = if !current_user.organization || ( !current_user.organization.shared || current_user.organization.shared == false )
  94. {
  95. 'query_string' => { 'default_field' => 'customer_id', 'query' => current_user.id }
  96. }
  97. # customer_id: XXX
  98. # conditions = [ 'customer_id = ?', current_user.id ]
  99. else
  100. {
  101. 'query_string' => { 'query' => "customer_id:#{current_user.id} OR organization_id:#{current_user.organization.id}" }
  102. }
  103. # customer_id: XXX OR organization_id: XXX
  104. # conditions = [ '( customer_id = ? OR organization_id = ? )', current_user.id, current_user.organization.id ]
  105. end
  106. end
  107. query_extention['bool']['must'].push access_condition
  108. items = SearchIndexBackend.search(query, limit, 'Ticket', query_extention, offset)
  109. if !full
  110. ids = []
  111. items.each do |item|
  112. ids.push item[:id]
  113. end
  114. return ids
  115. end
  116. tickets = []
  117. items.each do |item|
  118. ticket = Ticket.lookup(id: item[:id])
  119. next if !ticket
  120. tickets.push ticket
  121. end
  122. return tickets
  123. end
  124. # fallback do sql query
  125. access_condition = Ticket.access_condition(current_user, 'read')
  126. # do query
  127. # - stip out * we already search for *query* -
  128. if query
  129. query.delete! '*'
  130. tickets_all = Ticket.select('DISTINCT(tickets.id), tickets.created_at')
  131. .where(access_condition)
  132. .where('(tickets.title LIKE ? OR tickets.number LIKE ? OR ticket_articles.body LIKE ? OR ticket_articles.from LIKE ? OR ticket_articles.to LIKE ? OR ticket_articles.subject LIKE ?)', "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%" )
  133. .joins(:articles)
  134. .order('tickets.created_at DESC')
  135. .offset(offset)
  136. .limit(limit)
  137. else
  138. query_condition, bind_condition, tables = selector2sql(condition)
  139. tickets_all = Ticket.select('DISTINCT(tickets.id), tickets.created_at')
  140. .joins(tables)
  141. .where(access_condition)
  142. .where(query_condition, *bind_condition)
  143. .order('tickets.created_at DESC')
  144. .offset(offset)
  145. .limit(limit)
  146. end
  147. # build result list
  148. if !full
  149. ids = []
  150. tickets_all.each do |ticket|
  151. ids.push ticket.id
  152. end
  153. return ids
  154. end
  155. tickets = []
  156. tickets_all.each do |ticket|
  157. tickets.push Ticket.lookup(id: ticket.id)
  158. end
  159. tickets
  160. end
  161. end
  162. end