category.rb 3.7 KB

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