tag.rb 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. # Copyright (C) 2012-2023 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. =begin
  8. add tags for certain object
  9. Tag.tag_add(
  10. object: 'Ticket',
  11. o_id: ticket.id,
  12. item: 'some tag',
  13. created_by_id: current_user.id,
  14. )
  15. =end
  16. def self.tag_add(data)
  17. data[:item].strip!
  18. # lookups
  19. if data[:object]
  20. tag_object_id = Tag::Object.lookup_by_name_and_create(data[:object]).id
  21. end
  22. if data[:item]
  23. tag_item_id = Tag::Item.lookup_by_name_and_create(data[:item]).id
  24. end
  25. # return if duplicate
  26. current_tags = tag_list(data)
  27. return true if current_tags.include?(data[:item])
  28. # create history
  29. Tag.create(
  30. tag_object_id: tag_object_id,
  31. tag_item_id: tag_item_id,
  32. o_id: data[:o_id],
  33. created_by_id: data[:created_by_id],
  34. )
  35. # touch reference
  36. touch_reference_by_params(data)
  37. true
  38. end
  39. =begin
  40. remove tags of certain object
  41. Tag.tag_remove(
  42. object: 'Ticket',
  43. o_id: ticket.id,
  44. item: 'some tag',
  45. created_by_id: current_user.id,
  46. )
  47. or by ids
  48. Tag.tag_remove(
  49. tag_object_id: 123,
  50. o_id: ticket.id,
  51. tag_item_id: 123,
  52. created_by_id: current_user.id,
  53. )
  54. =end
  55. def self.tag_remove(data)
  56. # lookups
  57. if data[:object]
  58. data[:tag_object_id] = Tag::Object.lookup_by_name_and_create(data[:object]).id
  59. else
  60. data[:object] = Tag::Object.lookup(id: data[:tag_object_id]).name
  61. end
  62. if data[:item]
  63. data[:item].strip!
  64. data[:tag_item_id] = Tag::Item.lookup_by_name_and_create(data[:item]).id
  65. end
  66. # create history
  67. result = Tag.where(
  68. tag_object_id: data[:tag_object_id],
  69. tag_item_id: data[:tag_item_id],
  70. o_id: data[:o_id],
  71. )
  72. result.each(&:destroy)
  73. # touch reference
  74. touch_reference_by_params(data)
  75. true
  76. end
  77. =begin
  78. remove all tags of certain object
  79. Tag.tag_destroy(
  80. object: 'Ticket',
  81. o_id: ticket.id,
  82. created_by_id: current_user.id,
  83. )
  84. =end
  85. def self.tag_destroy(data)
  86. # lookups
  87. if data[:object]
  88. data[:tag_object_id] = Tag::Object.lookup_by_name_and_create(data[:object]).id
  89. else
  90. data[:object] = Tag::Object.lookup(id: data[:tag_object_id]).name
  91. end
  92. # create history
  93. result = Tag.where(
  94. tag_object_id: data[:tag_object_id],
  95. o_id: data[:o_id],
  96. )
  97. result.each(&:destroy)
  98. true
  99. end
  100. =begin
  101. update tags for certain object
  102. Tag.tag_update(
  103. object: 'Ticket',
  104. o_id: ticket.id,
  105. items: ['some tag', ['another tag']],
  106. created_by_id: current_user.id,
  107. )
  108. =end
  109. def self.tag_update(object:, o_id:, items:, created_by_id: nil)
  110. given_tags = items.map(&:strip!)
  111. old_tags = tag_list(object: object, o_id: o_id)
  112. tag_object_id = Tag::Object.lookup_by_name_and_create(object).id
  113. added_tags = given_tags - old_tags
  114. removed_tags = old_tags - given_tags
  115. added_tags.each do |tag_name|
  116. tag_item_id = Tag::Item.lookup_by_name_and_create(tag_name).id
  117. Tag.create(
  118. tag_object_id: tag_object_id,
  119. tag_item_id: tag_item_id,
  120. o_id: o_id,
  121. created_by_id: created_by_id,
  122. )
  123. end
  124. if removed_tags.any?
  125. tag_item_ids = removed_tags.map { |tag_name| Tag::Item.lookup_by_name_and_create(tag_name).id }
  126. Tag
  127. .where(
  128. tag_object_id: tag_object_id,
  129. tag_item_id: tag_item_ids,
  130. o_id: o_id,
  131. )
  132. .destroy_all
  133. end
  134. # touch reference
  135. if added_tags.any? || removed_tags.any?
  136. touch_reference_by_params(object: object, o_id: o_id)
  137. end
  138. true
  139. end
  140. =begin
  141. tag list for certain object
  142. tags = Tag.tag_list(
  143. object: 'Ticket',
  144. o_id: ticket.id,
  145. )
  146. returns
  147. ['tag 1', 'tag2', ...]
  148. =end
  149. def self.tag_list(data)
  150. Tag.joins(:tag_item, :tag_object)
  151. .where(o_id: data[:o_id], tag_objects: { name: data[:object] })
  152. .order(:id)
  153. .pluck('tag_items.name')
  154. end
  155. =begin
  156. Lists references to objects with certain tag. Optionally filter by type.
  157. Returns array containing object class name and ID.
  158. @param tag [String] tag to lookup
  159. @param object [String] optional name of the class to search in
  160. @example
  161. references = Tag.tag_references(
  162. tag: 'Tag',
  163. object: 'Ticket'
  164. )
  165. references # [['Ticket', 1], ['Ticket', 4], ...]
  166. @return [Array<Array<String, Integer>>]
  167. =end
  168. def self.tag_references(tag:, object: nil)
  169. tag_item = Tag::Item.find_by name: tag
  170. return [] if tag_item.nil?
  171. output = Tag.where(tag_item: tag_item).joins(:tag_object)
  172. output = output.where(tag_objects: { name: object }) if object.present?
  173. output.pluck(:'tag_objects.name', :o_id)
  174. end
  175. end