search_controller.rb 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. class SearchController < ApplicationController
  3. prepend_before_action :authentication_check
  4. # GET|POST /api/v1/search
  5. # GET|POST /api/v1/search/:objects
  6. def search_generic
  7. # enable search only for users with valid session
  8. if !current_user
  9. response_access_deny
  10. return true
  11. end
  12. # get params
  13. query = params[:query]
  14. limit = params[:limit] || 10
  15. # convert objects string into array of class names
  16. # e.g. user-ticket-another_object = %w( User Ticket AnotherObject )
  17. objects = if !params[:objects]
  18. Setting.get('models_searchable')
  19. else
  20. params[:objects].split('-').map(&:camelize)
  21. end
  22. # get priorities of result
  23. objects_in_order = []
  24. objects_in_order_hash = {}
  25. objects.each do |object|
  26. preferences = object.constantize.search_preferences(current_user)
  27. next if !preferences
  28. objects_in_order_hash[preferences[:prio]] = object
  29. end
  30. objects_in_order_hash.keys.sort.reverse_each do |prio|
  31. objects_in_order.push objects_in_order_hash[prio]
  32. end
  33. # try search index backend
  34. assets = {}
  35. result = []
  36. if SearchIndexBackend.enabled?
  37. # get direct search index based objects
  38. objects_with_direct_search_index = []
  39. objects_without_direct_search_index = []
  40. objects.each do |object|
  41. preferences = object.constantize.search_preferences(current_user)
  42. next if !preferences
  43. if preferences[:direct_search_index]
  44. objects_with_direct_search_index.push object
  45. else
  46. objects_without_direct_search_index.push object
  47. end
  48. end
  49. # do only one query to index search backend
  50. if objects_with_direct_search_index.present?
  51. items = SearchIndexBackend.search(query, limit, objects_with_direct_search_index)
  52. items.each do |item|
  53. require item[:type].to_filename
  54. record = Kernel.const_get(item[:type]).lookup(id: item[:id])
  55. next if !record
  56. assets = record.assets(assets)
  57. result.push item
  58. end
  59. end
  60. # e. g. do ticket query by Ticket class to handle ticket permissions
  61. objects_without_direct_search_index.each do |object|
  62. object_result = search_generic_backend(object, query, limit, current_user, assets)
  63. if object_result.present?
  64. result = result.concat(object_result)
  65. end
  66. end
  67. # sort order by object priority
  68. result_in_order = []
  69. objects_in_order.each do |object|
  70. result.each do |item|
  71. next if item[:type] != object
  72. item[:id] = item[:id].to_i
  73. result_in_order.push item
  74. end
  75. end
  76. result = result_in_order
  77. else
  78. # do query
  79. objects_in_order.each do |object|
  80. object_result = search_generic_backend(object, query, limit, current_user, assets)
  81. if object_result.present?
  82. result = result.concat(object_result)
  83. end
  84. end
  85. end
  86. render json: {
  87. assets: assets,
  88. result: result,
  89. }
  90. end
  91. private
  92. def search_generic_backend(object, query, limit, current_user, assets)
  93. found_objects = object.constantize.search(
  94. query: query,
  95. limit: limit,
  96. current_user: current_user,
  97. )
  98. result = []
  99. found_objects.each do |found_object|
  100. item = {
  101. id: found_object.id,
  102. type: found_object.class.to_s
  103. }
  104. result.push item
  105. assets = found_object.assets(assets)
  106. end
  107. result
  108. end
  109. end