category.rb 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. class KnowledgeBase::Category < ApplicationModel
  3. include HasTranslations
  4. include HasAgentAllowedParams
  5. include ChecksKbClientNotification
  6. include ChecksKbClientVisibility
  7. AGENT_ALLOWED_ATTRIBUTES = %i[knowledge_base_id parent_id category_icon].freeze
  8. AGENT_ALLOWED_NESTED_RELATIONS = %i[translations].freeze
  9. belongs_to :knowledge_base, inverse_of: :categories
  10. has_many :answers, class_name: 'KnowledgeBase::Answer',
  11. inverse_of: :category,
  12. dependent: :restrict_with_exception
  13. has_many :children, class_name: 'KnowledgeBase::Category',
  14. foreign_key: :parent_id,
  15. inverse_of: :parent,
  16. dependent: :restrict_with_exception
  17. belongs_to :parent, class_name: 'KnowledgeBase::Category',
  18. inverse_of: :children,
  19. touch: true,
  20. optional: true
  21. has_many :permissions, class_name: 'KnowledgeBase::Permission',
  22. as: :permissionable,
  23. autosave: true,
  24. dependent: :destroy
  25. validates :category_icon, presence: true
  26. scope :root, -> { where(parent: nil) }
  27. scope :sorted, -> { order(position: :asc) }
  28. acts_as_list scope: :parent, top_of_list: 0
  29. alias assets_essential assets
  30. def assets(data = {})
  31. return data if assets_added_to?(data)
  32. data = super(data)
  33. data = knowledge_base.assets(data)
  34. data = ApplicationModel::CanAssets.reduce(translations, data)
  35. # include parent category or KB for root to have full path
  36. (parent || knowledge_base).assets(data)
  37. end
  38. def self_parent?(candidate)
  39. return true if candidate == parent
  40. true if parent&.self_parent?(candidate)
  41. end
  42. def self_with_children
  43. [self] + children.map(&:self_with_children).flatten
  44. end
  45. def self_with_parents
  46. result = [self]
  47. check = self
  48. while check.parent.present?
  49. result << check.parent
  50. check = check.parent
  51. end
  52. result
  53. end
  54. def self_with_children_answers
  55. KnowledgeBase::Answer.where(category_id: self_with_children_ids)
  56. end
  57. def self_with_children_ids
  58. output = [id]
  59. output << KnowledgeBase::Category.where(parent_id: output.last).pluck(:id) while output.last.present?
  60. output.flatten
  61. end
  62. def full_destroy!
  63. transaction do
  64. answers.each(&:destroy!)
  65. answers.reset
  66. children.reset
  67. destroy!
  68. end
  69. end
  70. def public_content?(kb_locale = nil)
  71. scope = self_with_children_answers.published
  72. scope = scope.localed(kb_locale.system_locale) if kb_locale
  73. scope.any?
  74. end
  75. def internal_content?(kb_locale = nil)
  76. scope = self_with_children_answers.internal
  77. scope = scope.localed(kb_locale.system_locale) if kb_locale
  78. scope.any?
  79. end
  80. def visible?(kb_locale = nil)
  81. public_content?(kb_locale)
  82. end
  83. def api_url
  84. Rails.application.routes.url_helpers.knowledge_base_category_path(knowledge_base, self)
  85. end
  86. def permissions_effective
  87. cache_key = KnowledgeBase::Permission.cache_key self
  88. Rails.cache.fetch cache_key do
  89. KnowledgeBase::Category::Permission.new(self).permissions_effective
  90. end
  91. end
  92. def attributes_with_association_ids
  93. attrs = super
  94. attrs[:permissions_effective] = permissions_effective
  95. attrs
  96. end
  97. private
  98. def cannot_be_child_of_parent
  99. errors.add(:parent_id, __('cannot be a subcategory of the parent category')) if self_parent?(self)
  100. end
  101. validate :cannot_be_child_of_parent
  102. def sibling_categories
  103. parent&.children || knowledge_base.categories.root
  104. end
  105. end