has_attachments.rb 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. module ApplicationModel::HasAttachments
  3. extend ActiveSupport::Concern
  4. included do
  5. after_create :attachments_buffer_check
  6. after_update :attachments_buffer_check
  7. after_destroy :attachments_remove_all, if: :attachments_cleanup?
  8. class_attribute :attachments_cleanup, default: false
  9. end
  10. class_methods do
  11. =begin
  12. mark model for cleaning up after destroying
  13. =end
  14. def attachments_cleanup!
  15. self.attachments_cleanup = true
  16. end
  17. end
  18. def attachments_remove_all
  19. attachments.each { |attachment| Store.remove_item(attachment.id) }
  20. end
  21. =begin
  22. get list of attachments of this object
  23. item = Model.find(123)
  24. list = item.attachments
  25. returns
  26. # array with Store model objects
  27. =end
  28. def attachments
  29. Store.list(object: self.class.to_s, o_id: id)
  30. end
  31. =begin
  32. store attachments for this object
  33. item = Model.find(123)
  34. item.attachments = [ Store-Object1, Store-Object2 ]
  35. =end
  36. def attachments=(attachments)
  37. self.attachments_buffer = attachments
  38. # update if object already exists
  39. return if !id&.nonzero?
  40. attachments_buffer_check
  41. end
  42. =begin
  43. Returns attachments in ElasticSearch-compatible format
  44. For use in #search_index_attribute_lookup
  45. =end
  46. def attachments_for_search_index_attribute_lookup
  47. # list ignored file extensions
  48. attachments_ignore = Setting.get('es_attachment_ignore') || [ '.png', '.jpg', '.jpeg', '.mpeg', '.mpg', '.mov', '.bin', '.exe' ]
  49. # max attachment size
  50. attachment_max_size_in_mb = (Setting.get('es_attachment_max_size_in_mb') || 10).megabytes
  51. attachment_total_max_size_in_kb = 314_572.kilobytes
  52. attachment_total_max_size_in_kb_current = 0.kilobytes
  53. attachments.each_with_object([]) do |attachment, memo|
  54. # check if attachment exists
  55. next if !attachment.content
  56. size_in_bytes = attachment.content.size.bytes
  57. # check file size
  58. next if size_in_bytes > attachment_max_size_in_mb
  59. # check ignored files
  60. next if !attachment.filename || attachments_ignore.include?(File.extname(attachment.filename).downcase)
  61. # check if fits into total size limit
  62. next if attachment_total_max_size_in_kb_current + size_in_bytes > attachment_total_max_size_in_kb
  63. attachment_total_max_size_in_kb_current += size_in_bytes
  64. memo << {
  65. '_name' => attachment.filename,
  66. '_content' => Base64.encode64(attachment.content).delete("\n")
  67. }
  68. end
  69. end
  70. private
  71. def attachments_buffer
  72. @attachments_buffer_data
  73. end
  74. def attachments_buffer=(attachments)
  75. @attachments_buffer_data = attachments
  76. end
  77. def attachments_buffer_check
  78. # do nothing if no attachment exists
  79. return 1 if attachments_buffer.nil?
  80. # store attachments
  81. article_store = []
  82. attachments_buffer.each do |attachment|
  83. article_store.push Store.add(
  84. object: self.class.to_s,
  85. o_id: id,
  86. data: attachment.content,
  87. filename: attachment.filename,
  88. preferences: attachment.preferences,
  89. created_by_id: created_by_id,
  90. )
  91. end
  92. end
  93. end