tag.rb 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. class Tag < ApplicationModel
  3. include Tag::WritesToTicketHistory
  4. include HasTransactionDispatcher
  5. belongs_to :tag_object, class_name: 'Tag::Object', optional: true
  6. belongs_to :tag_item, class_name: 'Tag::Item', optional: true
  7. # the noop is needed since Layout/EmptyLines detects
  8. # the block commend below wrongly as the measurement of
  9. # the wanted indentation of the rubocop re-enabling above
  10. def noop; end
  11. =begin
  12. add tags for certain object
  13. Tag.tag_add(
  14. object: 'Ticket',
  15. o_id: ticket.id,
  16. item: 'some tag',
  17. created_by_id: current_user.id,
  18. )
  19. =end
  20. def self.tag_add(data)
  21. data[:item].strip!
  22. # lookups
  23. if data[:object]
  24. tag_object_id = Tag::Object.lookup_by_name_and_create(data[:object]).id
  25. end
  26. if data[:item]
  27. tag_item_id = Tag::Item.lookup_by_name_and_create(data[:item]).id
  28. end
  29. # return if duplicate
  30. current_tags = tag_list(data)
  31. return true if current_tags.include?(data[:item])
  32. # create history
  33. Tag.create(
  34. tag_object_id: tag_object_id,
  35. tag_item_id: tag_item_id,
  36. o_id: data[:o_id],
  37. created_by_id: data[:created_by_id],
  38. )
  39. # touch reference
  40. touch_reference_by_params(data)
  41. true
  42. end
  43. =begin
  44. remove tags of certain object
  45. Tag.tag_remove(
  46. object: 'Ticket',
  47. o_id: ticket.id,
  48. item: 'some tag',
  49. created_by_id: current_user.id,
  50. )
  51. or by ids
  52. Tag.tag_remove(
  53. tag_object_id: 123,
  54. o_id: ticket.id,
  55. tag_item_id: 123,
  56. created_by_id: current_user.id,
  57. )
  58. =end
  59. def self.tag_remove(data)
  60. # lookups
  61. if data[:object]
  62. data[:tag_object_id] = Tag::Object.lookup_by_name_and_create(data[:object]).id
  63. else
  64. data[:object] = Tag::Object.lookup(id: data[:tag_object_id]).name
  65. end
  66. if data[:item]
  67. data[:item].strip!
  68. data[:tag_item_id] = Tag::Item.lookup_by_name_and_create(data[:item]).id
  69. end
  70. # create history
  71. result = Tag.where(
  72. tag_object_id: data[:tag_object_id],
  73. tag_item_id: data[:tag_item_id],
  74. o_id: data[:o_id],
  75. )
  76. result.each(&:destroy)
  77. # touch reference
  78. touch_reference_by_params(data)
  79. true
  80. end
  81. =begin
  82. remove all tags of certain object
  83. Tag.tag_destroy(
  84. object: 'Ticket',
  85. o_id: ticket.id,
  86. created_by_id: current_user.id,
  87. )
  88. =end
  89. def self.tag_destroy(data)
  90. # lookups
  91. if data[:object]
  92. data[:tag_object_id] = Tag::Object.lookup_by_name_and_create(data[:object]).id
  93. else
  94. data[:object] = Tag::Object.lookup(id: data[:tag_object_id]).name
  95. end
  96. # create history
  97. result = Tag.where(
  98. tag_object_id: data[:tag_object_id],
  99. o_id: data[:o_id],
  100. )
  101. result.each(&:destroy)
  102. true
  103. end
  104. =begin
  105. tag list for certain object
  106. tags = Tag.tag_list(
  107. object: 'Ticket',
  108. o_id: ticket.id,
  109. )
  110. returns
  111. ['tag 1', 'tag2', ...]
  112. =end
  113. def self.tag_list(data)
  114. Tag.joins(:tag_item, :tag_object)
  115. .where(o_id: data[:o_id], tag_objects: { name: data[:object] })
  116. .order(:id)
  117. .pluck('tag_items.name')
  118. end
  119. =begin
  120. Lists references to objects with certain tag. Optionally filter by type.
  121. Returns array containing object class name and ID.
  122. @param tag [String] tag to lookup
  123. @param object [String] optional name of the class to search in
  124. @example
  125. references = Tag.tag_references(
  126. tag: 'Tag',
  127. object: 'Ticket'
  128. )
  129. references # [['Ticket', 1], ['Ticket', 4], ...]
  130. @return [Array<Array<String, Integer>>]
  131. =end
  132. def self.tag_references(tag:, object: nil)
  133. tag_item = Tag::Item.find_by name: tag
  134. return [] if tag_item.nil?
  135. output = Tag.where(tag_item: tag_item).joins(:tag_object)
  136. output = output.where(tag_objects: { name: object }) if object.present?
  137. output.pluck(:'tag_objects.name', :o_id)
  138. end
  139. end