state_machine.rb 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. module CanBePublished
  3. class StateMachine
  4. include AASM
  5. delegate :current_state, to: :aasm
  6. def initialize(record)
  7. @record = record
  8. aasm.current_state = calculated_state
  9. end
  10. def calculated_state
  11. matching_time = Time.zone.now
  12. state = %i[archived published internal].find { |state_name| calculated_state_valid?(state_name, matching_time) }
  13. state || :draft
  14. end
  15. def calculated_state_valid?(state_name, time)
  16. date = @record.send :"#{state_name}_at"
  17. date.present? && date < time
  18. end
  19. def set_timestamp
  20. override_unarchived_state if aasm.to_state == :unarchived
  21. @record.send :"#{aasm.to_state}_at=", Time.zone.now.change(sec: 0)
  22. end
  23. def override_unarchived_state
  24. aasm.to_state = @record.published_at.present? ? :published : :internal
  25. end
  26. def update_using_current_user(user)
  27. %i[archived internal published].each { |state_name| update_state_using_current_user(user, state_name) }
  28. end
  29. def update_state_using_current_user(user, state_name)
  30. return if !@record.send(:"#{state_name}_at_changed?")
  31. new_value = @record.send(:"#{state_name}_at").present? ? user : nil
  32. @record.send(:"#{state_name}_by=", new_value)
  33. end
  34. def clear_archived
  35. @record.archived_at = nil
  36. end
  37. def save_record
  38. @record.save!
  39. end
  40. aasm do
  41. state :draft, initial: true
  42. state :internal
  43. state :published
  44. state :archived
  45. state :unarchived # magic
  46. event :internal do
  47. transitions from: :draft,
  48. to: :internal,
  49. guard: :guard_internal?,
  50. after: :set_timestamp
  51. end
  52. event :publish do
  53. transitions from: %i[draft internal],
  54. to: :published,
  55. guard: :guard_publish?,
  56. after: :set_timestamp
  57. end
  58. event :archive do
  59. transitions from: %i[published internal],
  60. to: :archived,
  61. guard: :guard_archive?,
  62. after: :set_timestamp
  63. end
  64. event :unarchive do
  65. transitions from: :archived,
  66. to: :unarchived,
  67. guard: :guard_unarchive?,
  68. after: %i[clear_archived set_timestamp]
  69. end
  70. after_all_events %i[update_using_current_user save_record mark_as_idle]
  71. error_on_all_events :mark_as_idle
  72. end
  73. def mark_as_idle
  74. aasm.send(:current_event=, nil) # nullify current_event after transitioning
  75. end
  76. def guard_internal?
  77. draft?
  78. end
  79. def guard_publish?
  80. draft? || internal?
  81. end
  82. def guard_archive?
  83. internal? || published?
  84. end
  85. def guard_unarchive?
  86. archived?
  87. end
  88. end
  89. end