can_be_published.rb 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. module CanBePublished
  3. extend ActiveSupport::Concern
  4. def can_be_published_aasm
  5. @can_be_published_aasm ||= StateMachine.new(self)
  6. end
  7. def visible?
  8. can_be_published_aasm.published?
  9. end
  10. def visible_internally?
  11. can_be_published_aasm.internal? || visible?
  12. end
  13. class_methods do
  14. def inverse_relation_name(scope_name)
  15. "can_be_published_#{scope_name}_#{model_name.plural}"
  16. end
  17. end
  18. included do
  19. validate :archived_after_internal
  20. validate :archived_after_published
  21. validate :published_after_internal
  22. before_save :update_user_references
  23. after_save :schedule_touch
  24. after_save :update_active_publicly
  25. after_destroy :update_active_publicly
  26. after_touch :update_active_publicly
  27. %i[archived published internal].each do |scope_name|
  28. local = "#{scope_name}_by".to_sym
  29. remote = inverse_relation_name(scope_name).to_sym
  30. belongs_to local, class_name: 'User', inverse_of: remote, optional: true
  31. User.has_many remote, class_name: model_name, inverse_of: local, foreign_key: "#{local}_id"
  32. User.association_attributes_ignored remote
  33. end
  34. scope :published, lambda {
  35. timestamp = Time.zone.now
  36. date_earlier(:published_at, timestamp).date_later_or_nil(:archived_at, timestamp)
  37. }
  38. scope :archived, lambda {
  39. timestamp = Time.zone.now
  40. date_earlier(:archived_at, timestamp)
  41. }
  42. scope :only_internal, lambda {
  43. timestamp = Time.zone.now
  44. date_earlier(:internal_at, timestamp)
  45. .date_later_or_nil(:archived_at, timestamp)
  46. .date_later_or_nil(:published_at, timestamp)
  47. }
  48. scope :internal, lambda {
  49. timestamp = Time.zone.now
  50. internal = arel_table[:internal_at].lt(timestamp)
  51. published = arel_table[:published_at].lt(timestamp)
  52. where(internal.or(published))
  53. .date_later_or_nil(:archived_at, timestamp)
  54. }
  55. scope :date_earlier, lambda { |field, timestamp|
  56. where arel_table[field].lt(timestamp)
  57. }
  58. scope :date_later_or_nil, lambda { |field, timestamp|
  59. where arel_table[field].gt(timestamp).or(arel_table[field].eq(nil))
  60. }
  61. scope :check_published_unless_editor, lambda { |user|
  62. return if user&.permissions? 'knowledge_base.editor'
  63. published
  64. }
  65. scope :check_internal_unless_editor, lambda { |user|
  66. return if user&.permissions? 'knowledge_base.editor'
  67. return internal if user&.permissions? 'knowledge_base.reader'
  68. published
  69. }
  70. end
  71. def update_user_references
  72. return if can_be_published_aasm.aasm.current_event.present? # state machine is handling it
  73. %i[archived internal published].each do |scope_name|
  74. update_user_reference_item(scope_name)
  75. end
  76. end
  77. def update_user_reference_item(scope_name)
  78. return if !send("#{scope_name}_at_changed?")
  79. send("#{scope_name}_by_id=", UserInfo.current_user_id)
  80. end
  81. def archived_after_internal
  82. return if internal_at.nil? || archived_at.nil? || archived_at >= internal_at
  83. errors.add(:archived_at, 'date must be no earlier than internal at date')
  84. end
  85. def archived_after_published
  86. return if published_at.nil? || archived_at.nil? || archived_at >= published_at
  87. errors.add(:archived_at, 'date must be no earlier than published at date')
  88. end
  89. def published_after_internal
  90. return if published_at.nil? || internal_at.nil? || published_at >= internal_at
  91. errors.add(:published_at, 'date must be no earlier than internal at date')
  92. end
  93. def schedule_touch_for(attr)
  94. date = saved_changes[attr]&.last
  95. return if date.nil? || date <= Time.zone.now
  96. ScheduledTouchJob.touch_at(self, date)
  97. end
  98. def schedule_touch
  99. %i[published_at archived_at].each { |attr| schedule_touch_for(attr) }
  100. end
  101. def update_active_publicly
  102. CanBePublished.update_active_publicly!
  103. end
  104. def self.update_active_publicly!
  105. Setting.set('kb_active_publicly', active_publicly?)
  106. end
  107. def self.active_publicly?
  108. KnowledgeBase::Answer
  109. .published
  110. .joins(category: :knowledge_base)
  111. .where(knowledge_bases: { active: true })
  112. .exists?
  113. end
  114. end