can_assets.rb 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. module ApplicationModel::CanAssets
  3. extend ActiveSupport::Concern
  4. =begin
  5. get all assets / related models for this user
  6. user = User.find(123)
  7. result = user.assets(assets_if_exists)
  8. returns
  9. result = {
  10. :User => {
  11. 123 => user_model_123,
  12. 1234 => user_model_1234,
  13. }
  14. }
  15. =end
  16. def assets(data = {})
  17. app_model = self.class.to_app_model
  18. if !data[ app_model ]
  19. data[ app_model ] = {}
  20. end
  21. if !data[ app_model ][ id ]
  22. data[ app_model ][ id ] = attributes_with_association_ids
  23. end
  24. return data if !self['created_by_id'] && !self['updated_by_id']
  25. app_model_user = User.to_app_model
  26. %w[created_by_id updated_by_id].each do |local_user_id|
  27. next if !self[ local_user_id ]
  28. next if data[ app_model_user ] && data[ app_model_user ][ self[ local_user_id ] ]
  29. user = User.lookup(id: self[ local_user_id ])
  30. next if !user
  31. data = user.assets(data)
  32. end
  33. data
  34. end
  35. =begin
  36. get assets and record_ids of selector
  37. model = Model.find(123)
  38. assets = model.assets_of_selector('attribute_name_of_selector', assets)
  39. =end
  40. def assets_of_selector(selector, assets = {})
  41. # get assets of condition
  42. models = Models.all
  43. send(selector).each do |item, content|
  44. attribute = item.split('.')
  45. next if !attribute[1]
  46. if attribute[0] == 'customer' || attribute[0] == 'session'
  47. attribute[0] = 'user'
  48. end
  49. begin
  50. attribute_class = attribute[0].to_classname.constantize
  51. rescue => e
  52. next if attribute[0] == 'article'
  53. next if attribute[0] == 'execution_time'
  54. logger.error "Unable to get asset for '#{attribute[0]}': #{e.inspect}"
  55. next
  56. end
  57. if attribute_class == ::Notification
  58. next if content['recipient'].blank?
  59. attribute_ref_class = ::User
  60. item_ids = []
  61. Array(content['recipient']).each do |identifier|
  62. next if identifier !~ %r{\Auserid_(\d+)\z}
  63. item_ids.push($1)
  64. end
  65. else
  66. reflection = attribute[1].sub(%r{_id$}, '')
  67. next if !models[attribute_class]
  68. next if !models[attribute_class][:reflections]
  69. next if !models[attribute_class][:reflections][reflection]
  70. next if !models[attribute_class][:reflections][reflection].klass
  71. attribute_ref_class = models[attribute_class][:reflections][reflection].klass
  72. item_ids = Array(content['value'])
  73. end
  74. item_ids.each do |item_id|
  75. next if item_id.blank?
  76. attribute_object = attribute_ref_class.lookup(id: item_id)
  77. next if !attribute_object
  78. assets = attribute_object.assets(assets)
  79. end
  80. end
  81. assets
  82. end
  83. def assets_added_to?(data)
  84. data.dig(self.class.to_app_model, id).present?
  85. end
  86. # methods defined here are going to extend the class, not the instance of it
  87. class_methods do
  88. =begin
  89. return object and assets
  90. data = Model.full(123)
  91. data = {
  92. id: 123,
  93. assets: assets,
  94. }
  95. =end
  96. def full(id)
  97. object = find(id)
  98. assets = object.assets({})
  99. {
  100. id: object.id,
  101. assets: assets,
  102. }
  103. end
  104. =begin
  105. get assets of object list
  106. list = [
  107. {
  108. object => 'Ticket',
  109. o_id => 1,
  110. },
  111. {
  112. object => 'User',
  113. o_id => 121,
  114. },
  115. ]
  116. assets = Model.assets_of_object_list(list, assets)
  117. =end
  118. def assets_of_object_list(list, assets = {})
  119. list.each do |item|
  120. record = item['object'].constantize.lookup(id: item['o_id'])
  121. next if record.blank?
  122. assets = record.assets(assets)
  123. if item['created_by_id'].present?
  124. user = User.find(item['created_by_id'])
  125. assets = user.assets(assets)
  126. end
  127. if item['updated_by_id'].present?
  128. user = User.find(item['updated_by_id'])
  129. assets = user.assets(assets)
  130. end
  131. end
  132. assets
  133. end
  134. end
  135. =begin
  136. Compiles an assets hash for given items
  137. @param items [Array<CanAssets>] list of items responding to @see #assets
  138. @param data [Hash] given collection. Empty {} or assets collection in progress
  139. @param suffix [String] try to use non-default assets method
  140. @return [Hash] collection including assets of items
  141. @example
  142. list = Ticket.all
  143. ApplicationModel::CanAssets.reduce(list, {})
  144. =end
  145. def self.reduce(items, data = {}, suffix = nil)
  146. items.reduce(data) do |memo, elem|
  147. method_name = if suffix.present? && elem.respond_to?("assets_#{suffix}")
  148. "assets_#{suffix}"
  149. else
  150. :assets
  151. end
  152. elem.send method_name, memo
  153. end
  154. end
  155. end