123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- class KnowledgeBase::Category < ApplicationModel
- include HasTranslations
- include HasAgentAllowedParams
- include ChecksKbClientNotification
- include ChecksKbClientVisibility
- AGENT_ALLOWED_ATTRIBUTES = %i[knowledge_base_id parent_id category_icon].freeze
- AGENT_ALLOWED_NESTED_RELATIONS = %i[translations].freeze
- belongs_to :knowledge_base, inverse_of: :categories
- has_many :answers, class_name: 'KnowledgeBase::Answer',
- inverse_of: :category,
- dependent: :restrict_with_exception
- has_many :children, class_name: 'KnowledgeBase::Category',
- foreign_key: :parent_id,
- inverse_of: :parent,
- dependent: :restrict_with_exception
- belongs_to :parent, class_name: 'KnowledgeBase::Category',
- inverse_of: :children,
- touch: true,
- optional: true
- has_many :permissions, class_name: 'KnowledgeBase::Permission',
- as: :permissionable,
- autosave: true,
- dependent: :destroy
- validates :category_icon, presence: true
- validate :cannot_be_child_of_parent
- scope :root, -> { where(parent: nil) }
- scope :sorted, -> { order(position: :asc) }
- acts_as_list scope: :parent, top_of_list: 0
- alias assets_essential assets
- def assets(data = {})
- return data if assets_added_to?(data)
- data = super
- data = knowledge_base.assets(data)
- data = ApplicationModel::CanAssets.reduce(translations, data)
- # include parent category or KB for root to have full path
- (parent || knowledge_base).assets(data)
- end
- def self_parent?(candidate)
- return true if candidate == parent
- true if parent&.self_parent?(candidate)
- end
- def self_with_children
- [self] + children.map(&:self_with_children).flatten
- end
- def self_with_parents
- result = [self]
- check = self
- while check.parent.present?
- result << check.parent
- check = check.parent
- end
- result
- end
- def self_with_children_answers
- KnowledgeBase::Answer.where(category_id: self_with_children_ids)
- end
- def self_with_children_ids
- output = [id]
- output << KnowledgeBase::Category.where(parent_id: output.last).pluck(:id) while output.last.present?
- output.flatten
- end
- def full_destroy!
- transaction do
- answers.each(&:destroy!)
- answers.reset
- children.reset
- destroy!
- end
- end
- def public_content?(kb_locale = nil)
- scope = self_with_children_answers.published
- scope = scope.localed(kb_locale.system_locale) if kb_locale
- scope.any?
- end
- def internal_content?(kb_locale = nil)
- scope = self_with_children_answers.internal
- scope = scope.localed(kb_locale.system_locale) if kb_locale
- scope.any?
- end
- def visible?(kb_locale = nil)
- public_content?(kb_locale)
- end
- def api_url
- Rails.application.routes.url_helpers.knowledge_base_category_path(knowledge_base, self)
- end
- def permissions_effective
- cache_key = KnowledgeBase::Permission.cache_key self
- Rails.cache.fetch cache_key do
- KnowledgeBase::Category::Permission.new(self).permissions_effective
- end
- end
- def attributes_with_association_ids
- attrs = super
- attrs[:permissions_effective] = permissions_effective
- attrs
- end
- private
- def cannot_be_child_of_parent
- errors.add(:parent_id, __('cannot be a subcategory of the parent category')) if self_parent?(self)
- end
- def sibling_categories
- parent&.children || knowledge_base.categories.root
- end
- end
|