search_controller.rb 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class KnowledgeBase::SearchController < ApplicationController
  3. skip_before_action :verify_csrf_token
  4. prepend_before_action :authentication_check_only
  5. include KnowledgeBaseHelper
  6. include ActionView::Helpers::SanitizeHelper
  7. include CanPaginate
  8. # POST /api/v1/knowledge_bases/search
  9. # knowledge_base_id, locale, flavor, index, page, per_page, limit, include_locale
  10. def search
  11. knowledge_base = KnowledgeBase
  12. .active
  13. .find_by id: params[:knowledge_base_id]
  14. kb_locale = knowledge_base
  15. &.kb_locales
  16. &.joins(:system_locale)
  17. &.find_by(locales: { locale: params[:locale] })
  18. scope = knowledge_base
  19. &.categories
  20. &.find_by(id: params[:scope_id])
  21. search_backend = SearchKnowledgeBaseBackend.new(
  22. knowledge_base: knowledge_base,
  23. locale: kb_locale,
  24. scope: scope,
  25. flavor: params[:flavor],
  26. index: params[:index],
  27. limit: params[:limit],
  28. highlight_enabled: params[:highlight_enabled],
  29. order_by: { updated_at: :desc }
  30. )
  31. include_locale = params[:include_locale] && KnowledgeBase.with_multiple_locales_exists?
  32. result = search_backend.search params[:query], user: current_user, pagination: pagination
  33. if (exclude_ids = params[:exclude_ids]&.map(&:to_i))
  34. result.reject! { |meta| meta[:type] == params[:index] && exclude_ids.include?(meta[:id]) }
  35. end
  36. details = result.map { |item| public_item_details(item, include_locale) }
  37. render json: {
  38. result: result,
  39. details: details,
  40. }
  41. end
  42. private
  43. def item_assets(meta)
  44. object = meta[:type].constantize.find(meta[:id])
  45. object.assets
  46. end
  47. def public_item_details(meta, include_locale)
  48. object = meta[:type].constantize.find(meta[:id])
  49. output = case object
  50. when KnowledgeBase::Answer::Translation
  51. public_item_details_answer(meta, object)
  52. when KnowledgeBase::Category::Translation
  53. public_item_details_category(meta, object)
  54. when KnowledgeBase::Translation
  55. public_item_details_base(meta, object)
  56. end
  57. if include_locale && (system_locale = object.kb_locale.system_locale)
  58. output[:title] += " (#{system_locale.locale.upcase})"
  59. end
  60. output
  61. end
  62. def public_item_details_answer(meta, object)
  63. category_translation = object.answer.category.translation_preferred(object.kb_locale)
  64. path = help_answer_path(category_translation, object, locale: object.kb_locale.system_locale.locale)
  65. subtitle = object.answer.category.self_with_parents.map { |c| strip_tags(c.translation_preferred(object.kb_locale).title) }.reverse
  66. subtitle = if subtitle.count <= 2
  67. subtitle.join(' > ')
  68. else
  69. subtitle.values_at(0, -1).join(' > .. > ')
  70. end
  71. url = case url_type
  72. when :public
  73. custom_path_if_needed(path, object.answer.category.knowledge_base)
  74. when :agent
  75. knowledge_base_answer_path(object.answer.category.knowledge_base, object.answer) + "?include_contents=#{object.id}"
  76. end
  77. {
  78. id: object.id,
  79. type: object.class.name,
  80. icon: 'knowledge-base-answer',
  81. date: object.updated_at,
  82. url: url,
  83. title: meta.dig(:highlight, 'title')&.first || object.title,
  84. subtitle: subtitle,
  85. body: meta.dig(:highlight, 'content.body')&.first || strip_tags(object.content.body).truncate(100),
  86. tags: object.answer.tag_list
  87. }
  88. end
  89. def public_item_details_category(meta, object)
  90. parent_category_translation = object.category.parent&.translation_preferred(object.kb_locale)
  91. path = help_category_path(object, locale: object.kb_locale.system_locale.locale)
  92. url = case url_type
  93. when :public
  94. custom_path_if_needed(path, object.category.knowledge_base)
  95. when :agent
  96. knowledge_base_category_path(object.category.knowledge_base, object.category)
  97. end
  98. {
  99. id: object.id,
  100. type: object.class.name,
  101. fontName: object.category.knowledge_base.iconset,
  102. date: object.updated_at,
  103. url: url,
  104. icon: object.category.category_icon,
  105. subtitle: strip_tags(parent_category_translation&.title.presence),
  106. title: meta.dig(:highlight, 'title')&.first || strip_tags(object.title)
  107. }
  108. end
  109. def public_item_details_base(meta, object)
  110. path = help_root_path(object.kb_locale.system_locale.locale)
  111. url = case url_type
  112. when :public
  113. custom_path_if_needed(path, object.knowledge_base)
  114. when :agent
  115. knowledge_base_path(object.knowledge_base)
  116. end
  117. {
  118. id: object.id,
  119. type: object.class.name,
  120. icon: 'knowledge-base',
  121. date: object.updated_at,
  122. url: url,
  123. title: meta.dig(:highlight, 'title')&.first || strip_tags(object.title)
  124. }
  125. end
  126. def url_type
  127. params[:url_type]&.to_sym || :public
  128. end
  129. end