mirror of
https://github.com/zammad/zammad
synced 2026-05-24 09:48:36 +00:00
Co-authored-by: Marcel Bialas <mb@zammad.com> Co-authored-by: Dominik Klein <dk@zammad.com> Co-authored-by: Florian Liebe <fl@zammad.com>
107 lines
3.3 KiB
Ruby
107 lines
3.3 KiB
Ruby
# Copyright (C) 2012-2026 Zammad Foundation, https://zammad-foundation.org/
|
|
|
|
class KnowledgeBase::Answer::Translation < ApplicationModel
|
|
include HasDefaultModelUserRelations
|
|
include HasOnlineNotifications
|
|
|
|
include HasAgentAllowedParams
|
|
include HasLinks
|
|
include HasSearchIndexBackend
|
|
include HasVectorIndex
|
|
include KnowledgeBase::HasUniqueTitle
|
|
include KnowledgeBase::Answer::Translation::Search
|
|
|
|
AGENT_ALLOWED_ATTRIBUTES = %i[title kb_locale_id].freeze
|
|
AGENT_ALLOWED_NESTED_RELATIONS = %i[content].freeze
|
|
|
|
belongs_to :kb_locale, class_name: 'KnowledgeBase::Locale', inverse_of: :answer_translations
|
|
belongs_to :answer, class_name: 'KnowledgeBase::Answer', inverse_of: :translations, touch: true
|
|
|
|
belongs_to :content, class_name: 'KnowledgeBase::Answer::Translation::Content', inverse_of: :translation, dependent: :destroy
|
|
accepts_nested_attributes_for :content, update_only: true
|
|
|
|
validates :title, presence: true, length: { maximum: 250 }
|
|
validates :kb_locale_id, uniqueness: { case_sensitive: true, scope: :answer_id }
|
|
|
|
scope :neighbours_of, ->(translation) { joins(:answer).where(knowledge_base_answers: { category_id: translation.answer&.category_id }) }
|
|
|
|
alias assets_essential assets
|
|
|
|
def assets(data = {})
|
|
return data if assets_added_to?(data)
|
|
|
|
data = super
|
|
answer.assets(data)
|
|
ApplicationModel::CanAssets.reduce inline_linked_objects, data
|
|
end
|
|
|
|
def to_param
|
|
[answer_id, title.parameterize].join('-')
|
|
end
|
|
|
|
def search_index_attribute_lookup(include_references: true)
|
|
attrs = super
|
|
|
|
attrs['title'] = ActionController::Base.helpers.strip_tags(title)
|
|
attrs['content'] = content&.search_index_attribute_lookup
|
|
attrs['scope_id'] = answer.category_id
|
|
attrs['tags'] = answer.tag_list
|
|
attrs['attachment'] = answer.search_index_attachments_lookup(attrs.to_json.bytesize)
|
|
|
|
attrs
|
|
end
|
|
|
|
def vector_index_data
|
|
{
|
|
content: "#{title}\n#{content.body.html2text}",
|
|
metadata: {
|
|
locale: kb_locale.system_locale.locale,
|
|
category_id: answer.category_id,
|
|
},
|
|
}
|
|
end
|
|
|
|
def vector_indexing_for_record?
|
|
return false if !answer.visible_internally?
|
|
|
|
# For now only explicitly enabled categories or all are indexed.
|
|
relevant_categorie_ids = ENV.fetch('VECTOR_INDEX_FOR_KNOWLEDGE_BASE_CATEGORY_IDS', nil)
|
|
return false if relevant_categorie_ids&.split(',')&.exclude?(answer.category_id.to_s)
|
|
|
|
true
|
|
end
|
|
|
|
def inline_linked_objects
|
|
output = []
|
|
|
|
scrubber = Loofah::Scrubber.new do |node|
|
|
next if node.name != 'a'
|
|
next if !node.key? 'data-target-type'
|
|
|
|
case node['data-target-type']
|
|
when 'knowledge-base-answer'
|
|
if (translation = KnowledgeBase::Answer::Translation.find_by(id: node['data-target-id']))
|
|
output.push translation
|
|
end
|
|
end
|
|
end
|
|
|
|
Loofah.scrub_fragment(content.body, scrubber)
|
|
|
|
output
|
|
end
|
|
|
|
scope :search_sql_text_fallback, lambda { |query|
|
|
fields = %w[title]
|
|
fields << KnowledgeBase::Answer::Translation::Content.arel_table[:body]
|
|
|
|
where_or_cis(fields, query).joins(:content)
|
|
}
|
|
|
|
scope :apply_kb_scope, lambda { |scope|
|
|
if scope.present?
|
|
joins(:answer)
|
|
.where(knowledge_base_answers: { category_id: scope })
|
|
end
|
|
}
|
|
end
|