tag.rb 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. class Tag < ApplicationModel
  3. belongs_to :tag_object, class_name: 'Tag::Object'
  4. belongs_to :tag_item, class_name: 'Tag::Item'
  5. # the noop is needed since Layout/EmptyLines detects
  6. # the block commend below wrongly as the measurement of
  7. # the wanted indentation of the rubocop re-enabling above
  8. def noop; end
  9. =begin
  10. add tags for certain object
  11. Tag.tag_add(
  12. object: 'Ticket',
  13. o_id: ticket.id,
  14. item: 'some tag',
  15. created_by_id: current_user.id,
  16. )
  17. =end
  18. def self.tag_add(data)
  19. data[:item].strip!
  20. # lookups
  21. if data[:object]
  22. tag_object_id = Tag::Object.lookup_by_name_and_create(data[:object]).id
  23. end
  24. if data[:item]
  25. tag_item_id = Tag::Item.lookup_by_name_and_create(data[:item]).id
  26. end
  27. # return if duplicate
  28. current_tags = tag_list(data)
  29. return true if current_tags.include?(data[:item])
  30. # create history
  31. Tag.create(
  32. tag_object_id: tag_object_id,
  33. tag_item_id: tag_item_id,
  34. o_id: data[:o_id],
  35. created_by_id: data[:created_by_id],
  36. )
  37. # touch reference
  38. touch_reference_by_params(data)
  39. true
  40. end
  41. =begin
  42. remove tags of certain object
  43. Tag.tag_remove(
  44. object: 'Ticket',
  45. o_id: ticket.id,
  46. item: 'some tag',
  47. created_by_id: current_user.id,
  48. )
  49. or by ids
  50. Tag.tag_remove(
  51. tag_object_id: 123,
  52. o_id: ticket.id,
  53. tag_item_id: 123,
  54. created_by_id: current_user.id,
  55. )
  56. =end
  57. def self.tag_remove(data)
  58. # lookups
  59. if data[:object]
  60. data[:tag_object_id] = Tag::Object.lookup_by_name_and_create(data[:object]).id
  61. else
  62. data[:object] = Tag::Object.lookup(id: data[:tag_object_id]).name
  63. end
  64. if data[:item]
  65. data[:item].strip!
  66. data[:tag_item_id] = Tag::Item.lookup_by_name_and_create(data[:item]).id
  67. end
  68. # create history
  69. result = Tag.where(
  70. tag_object_id: data[:tag_object_id],
  71. tag_item_id: data[:tag_item_id],
  72. o_id: data[:o_id],
  73. )
  74. result.each(&:destroy)
  75. # touch reference
  76. touch_reference_by_params(data)
  77. true
  78. end
  79. =begin
  80. remove all tags of certain object
  81. Tag.tag_destroy(
  82. object: 'Ticket',
  83. o_id: ticket.id,
  84. created_by_id: current_user.id,
  85. )
  86. =end
  87. def self.tag_destroy(data)
  88. # lookups
  89. if data[:object]
  90. data[:tag_object_id] = Tag::Object.lookup_by_name_and_create(data[:object]).id
  91. else
  92. data[:object] = Tag::Object.lookup(id: data[:tag_object_id]).name
  93. end
  94. # create history
  95. result = Tag.where(
  96. tag_object_id: data[:tag_object_id],
  97. o_id: data[:o_id],
  98. )
  99. result.each(&:destroy)
  100. true
  101. end
  102. =begin
  103. tag list for certain object
  104. tags = Tag.tag_list(
  105. object: 'Ticket',
  106. o_id: ticket.id,
  107. )
  108. returns
  109. ['tag 1', 'tag2', ...]
  110. =end
  111. def self.tag_list(data)
  112. tag_object_id_requested = Tag::Object.lookup(name: data[:object])
  113. return [] if !tag_object_id_requested
  114. tag_search = Tag.where(
  115. tag_object_id: tag_object_id_requested,
  116. o_id: data[:o_id],
  117. ).order(:id)
  118. tag_search.each_with_object([]) do |tag, result|
  119. tag_item = Tag::Item.lookup(id: tag.tag_item_id)
  120. next if !tag_item
  121. result.push tag_item.name
  122. end
  123. end
  124. class Object < ApplicationModel
  125. validates :name, presence: true
  126. =begin
  127. lookup by name and create tag item
  128. tag_object = Tag::Object.lookup_by_name_and_create('some tag')
  129. =end
  130. def self.lookup_by_name_and_create(name)
  131. name.strip!
  132. tag_object = Tag::Object.lookup(name: name)
  133. return tag_object if tag_object
  134. Tag::Object.create(name: name)
  135. end
  136. end
  137. class Item < ApplicationModel
  138. validates :name, presence: true
  139. before_save :fill_namedowncase
  140. =begin
  141. lookup by name and create tag item
  142. tag_item = Tag::Item.lookup_by_name_and_create('some tag')
  143. =end
  144. def self.lookup_by_name_and_create(name)
  145. name.strip!
  146. tag_item = Tag::Item.lookup(name: name)
  147. return tag_item if tag_item
  148. Tag::Item.create(name: name)
  149. end
  150. =begin
  151. rename tag items
  152. Tag::Item.rename(
  153. id: existing_tag_item_to_rename,
  154. name: 'new tag item name',
  155. updated_by_id: current_user.id,
  156. )
  157. =end
  158. def self.rename(data)
  159. new_tag_name = data[:name].strip
  160. old_tag_item = Tag::Item.find(data[:id])
  161. already_existing_tag = Tag::Item.lookup(name: new_tag_name)
  162. # check if no remame is needed
  163. return true if new_tag_name == old_tag_item.name
  164. # merge old with new tag if already existing
  165. if already_existing_tag
  166. # re-assign old tag to already existing tag
  167. Tag.where(tag_item_id: old_tag_item.id).each do |tag|
  168. # check if tag already exists on object
  169. if Tag.find_by(tag_object_id: tag.tag_object_id, o_id: tag.o_id, tag_item_id: already_existing_tag.id)
  170. Tag.tag_remove(
  171. tag_object_id: tag.tag_object_id,
  172. o_id: tag.o_id,
  173. tag_item_id: old_tag_item.id,
  174. )
  175. next
  176. end
  177. # re-assign
  178. tag_object = Tag::Object.lookup(id: tag.tag_object_id)
  179. tag.tag_item_id = already_existing_tag.id
  180. tag.save
  181. # touch reference objects
  182. Tag.touch_reference_by_params(
  183. object: tag_object.name,
  184. o_id: tag.o_id,
  185. )
  186. end
  187. # delete not longer used tag
  188. old_tag_item.destroy
  189. return true
  190. end
  191. update_referenced_objects(old_tag_item.name, new_tag_name)
  192. # update new tag name
  193. old_tag_item.name = new_tag_name
  194. old_tag_item.save
  195. # touch reference objects
  196. Tag.where(tag_item_id: old_tag_item.id).each do |tag|
  197. tag_object = Tag::Object.lookup(id: tag.tag_object_id)
  198. Tag.touch_reference_by_params(
  199. object: tag_object.name,
  200. o_id: tag.o_id,
  201. )
  202. end
  203. true
  204. end
  205. =begin
  206. remove tag item (destroy with reverences)
  207. Tag::Item.remove(id)
  208. =end
  209. def self.remove(id)
  210. # search for references, destroy and touch
  211. Tag.where(tag_item_id: id).each do |tag|
  212. tag_object = Tag::Object.lookup(id: tag.tag_object_id)
  213. tag.destroy
  214. Tag.touch_reference_by_params(
  215. object: tag_object.name,
  216. o_id: tag.o_id,
  217. )
  218. end
  219. Tag::Item.find(id).destroy
  220. true
  221. end
  222. def fill_namedowncase
  223. self.name_downcase = name.downcase
  224. true
  225. end
  226. =begin
  227. Update referenced objects such as triggers, overviews, schedulers, and postmaster filters
  228. Specifically, the following fields are updated:
  229. Overview.condition
  230. Trigger.condition Trigger.perform
  231. Job.condition Job.perform
  232. PostmasterFilter.perform
  233. =end
  234. def self.update_referenced_objects(old_name, new_name)
  235. objects = Overview.all + Trigger.all + Job.all + PostmasterFilter.all
  236. objects.each do |object|
  237. changed = false
  238. if object.has_attribute?(:condition)
  239. changed |= update_condition_hash object.condition, old_name, new_name
  240. end
  241. if object.has_attribute?(:perform)
  242. changed |= update_condition_hash object.perform, old_name, new_name
  243. end
  244. object.save if changed
  245. end
  246. end
  247. def self.update_condition_hash(hash, old_name, new_name)
  248. changed = false
  249. hash.each do |key, condition|
  250. next if %w[ticket.tags x-zammad-ticket-tags].exclude? key
  251. next if condition[:value].split(', ').exclude? old_name
  252. condition[:value] = update_name(condition[:value], old_name, new_name)
  253. changed = true
  254. end
  255. changed
  256. end
  257. def self.update_name(condition, old_name, new_name)
  258. tags = condition.split(', ')
  259. return new_name if tags.size == 1
  260. tags = tags.map { |t| t == old_name ? new_name : t }
  261. tags.join(', ')
  262. end
  263. end
  264. end