can_clone_attachments.rb 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. module CanCloneAttachments
  3. extend ActiveSupport::Concern
  4. =begin
  5. clone existing attachments of article to the target object
  6. article_parent = Ticket::Article.find(123)
  7. article_new = Ticket::Article.find(456)
  8. attached_attachments = article_parent.clone_attachments(article_new.class.name, article_new.id, only_attached_attachments: true)
  9. inline_attachments = article_parent.clone_attachments(article_new.class.name, article_new.id, only_inline_attachments: true)
  10. returns
  11. [attachment1, attachment2, ...]
  12. =end
  13. def clone_attachments(object_type, object_id, options = {})
  14. existing_attachments = Store.list(
  15. object: object_type,
  16. o_id: object_id,
  17. )
  18. is_html_content = false
  19. if content_type.present? && content_type =~ %r{text/html}i
  20. is_html_content = true
  21. end
  22. new_attachments = []
  23. attachments.each do |new_attachment|
  24. next if new_attachment.preferences['content-alternative'] == true
  25. # only_attached_attachments mode is used by apply attached attachments to forwared article
  26. if options[:only_attached_attachments] == true && is_html_content == true
  27. content_id = new_attachment.preferences['Content-ID'] || new_attachment.preferences['content_id']
  28. next if content_id.present? && body.present? && body.match?(%r{#{Regexp.quote(content_id)}}i)
  29. end
  30. # only_inline_attachments mode is used when quoting HTML mail with #{article.body_as_html}
  31. if options[:only_inline_attachments] == true
  32. next if is_html_content == false
  33. next if body.blank?
  34. content_disposition = new_attachment.preferences['Content-Disposition'] || new_attachment.preferences['content_disposition']
  35. next if content_disposition.present? && content_disposition.exclude?('inline')
  36. content_id = new_attachment.preferences['Content-ID'] || new_attachment.preferences['content_id']
  37. next if content_id.blank?
  38. next if !body.match?(%r{#{Regexp.quote(content_id)}}i)
  39. end
  40. already_added = false
  41. existing_attachments.each do |existing_attachment|
  42. next if existing_attachment.filename != new_attachment.filename || existing_attachment.size != new_attachment.size
  43. already_added = true
  44. break
  45. end
  46. next if already_added == true
  47. file = Store.create!(
  48. object: object_type,
  49. o_id: object_id,
  50. data: new_attachment.content,
  51. filename: new_attachment.filename,
  52. preferences: new_attachment.preferences,
  53. )
  54. new_attachments.push file
  55. end
  56. new_attachments
  57. end
  58. def attach_upload_cache(form_id, source_object_name: 'UploadCache')
  59. attachments_remove_all
  60. Store
  61. .list(object: source_object_name, o_id: form_id)
  62. .map do |old_attachment|
  63. Store.create!(
  64. object: self.class.name,
  65. o_id: id,
  66. data: old_attachment.content,
  67. filename: old_attachment.filename,
  68. preferences: old_attachment.preferences,
  69. )
  70. end
  71. end
  72. end